diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8de5b6f --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Gradle +.gradle +# Eclipse, ... +.settings +bin +build +doc +# Testing +ext/** +projects +.project +petep.json +.classpath +src/test/** + +!ext/README.txt \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..678e471 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,21 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [1.2.1] - 2020-05-31 +### Added +- version checks +- small bugfixes + +## [1.2.0] - 2020-04-15 +### Added +- encoding (charsets) +- new byte editor with charset support +- SAST, refactoring +### Removed +- old byte editor + +## [1.1.0] - 2020-04-15 +### Added +- bugfixes +- performance improvements \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..2fb2e74 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,675 @@ +### 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.md b/README.md new file mode 100644 index 0000000..5f76068 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# PETEP - PEnetration TEsting Proxy +PETEP is open-source Java application for network communication proxying for the purpose of penetration testing. + +Currently PETEP supports primarily TCP (with SSL/TLS support). + +You can find out more about PETEP on the following website: http://petep.warxim.com/ + +## Using PETEP with tools for HTTP +PETEP allows you to use your favorite tools for web penetration testing (like Burp, Zap etc.) for non-HTTP traffic. + +See http://petep.warxim.com/user-guide/#external-http-proxy. + +## Extensibility +It is possible to develop extensions using Java to implement support for new protocols and/or to implement new functionality. + +For more information about extension development, please see http://petep.warxim.com/dev-guide/. + +## License +PETEP is licensed under GNU GPL 3.0. \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..6a43247 --- /dev/null +++ b/build.gradle @@ -0,0 +1,135 @@ +/* + * PETEP Gradle Build + */ + +plugins { + id 'java-library' + id 'java' + id 'eclipse' + id 'application' + id 'org.openjfx.javafxplugin' version '0.0.8' + id "org.sonarqube" version "2.8" +} + +repositories { + jcenter() +} + +javafx { + version = "11.0.2" + modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.web' ] +} + +dependencies { + implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6' + + testImplementation('org.junit.jupiter:junit-jupiter:5.4.2') +} + +// UTF-8 encoding +compileJava.options.encoding = 'UTF-8' + +mainClassName='com.warxim.petep.Main' + +// Copy extensions from their build/libs/ to projects ext/ +task copyExtensions (type: Copy, dependsOn: gradle.includedBuilds*.task(':jar')) { + into 'ext/' + + gradle.includedBuilds.each { build -> + println 'Moving extension "' + build.rootDirectory + '" to ext/ directory.' + from build.rootDirectory.path + '/build/libs/' + } +} + +// Run task +run { + if (gradle.ext.wizard) { + args = [] + } else { + if (gradle.GUI) { + args = [gradle.ext.testProjectDirectory] + } else { + args = [gradle.ext.testProjectDirectory, "--nogui"] + } + } + dependsOn gradle.includedBuilds*.task(':jar'), copyExtensions +} + +// Export com.sun.javafx.css (for css editing) +application { + applicationDefaultJvmArgs = [ + "--add-opens=javafx.graphics/com.sun.javafx.css=ALL-UNNAMED" + ] +} + +// Create jar library for extensions +task petepLibJar(type: Jar) { + println "Creating jar library" + includes = includedFiles(sourceSets.main.allSource.files) + baseName = "PetepLib" + with jar +} + +// Create fat jar +jar { + from(sourceSets.main.output) { + println "Creating fat jar" + manifest { + attributes 'Main-Class': "$mainClassName" + } + baseName = 'PETEP' + from { + configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } + } + } + duplicatesStrategy = 'exclude' +} + +// Include only @PetepAPI classes to jar +def includedFiles(Collection files) { + List included = new ArrayList<>() + files.each { file -> + if (file.isDirectory()) { + excludedFiles(Arrays.asList(file.listFiles())) + } else { + if (file.text.contains("@PetepAPI") || file.text.contains("")) { + String temp = projectDir.toURI().relativize( + file.toURI()).toString() + .replace(".java", ".class") + .replace("src/main/java/", "") + .replace("src/main/resources/", "") + included += temp + println "- including: " + temp + } + } + } + return included +} + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + +distributions { + main { + contents { + exclude 'PETEP', 'PETEP.bat' + + from("LICENSE.md") { + into "" + } + + from(petepLibJar) { + into "api" + } + + from("ext") { + into "ext" + } + + from("project_template") { + into "project_template" + } + } + } +} \ No newline at end of file diff --git a/ext/README.txt b/ext/README.txt new file mode 100644 index 0000000..4d53661 --- /dev/null +++ b/ext/README.txt @@ -0,0 +1 @@ +It is recommended to place your extensions into this directory. \ No newline at end of file diff --git a/project_template/conf/README.txt b/project_template/conf/README.txt new file mode 100644 index 0000000..29e14f3 --- /dev/null +++ b/project_template/conf/README.txt @@ -0,0 +1 @@ +This is default PETEP project template. \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..bc787a4 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,27 @@ +/* + * PETEP Gradle Settings + */ + +rootProject.name = 'PETEP' + +// If "gradle.ext.wizard" is set to "false", gradle "Run" will run PETEP with project (gradle.ext.testProjectDirectory) automatically. +gradle.ext.wizard = true + +// If GUI is set to "false", gradle "Run" will run PETEP without GUI. +gradle.ext.GUI = true + +// Path to project to open automatically when "gradle.ext.wizard" is set to "false". +gradle.ext.testProjectDirectory = './projects/test_project' + +// Include external extensions to gradle build? +gradle.ext.extensions = false + +// Path to extensions to automatically include (useful for extension development). +gradle.ext.extensionsDirectory = '../petep_extensions/' + +// Include extensions +if (gradle.ext.extensions) { + file(gradle.ext.extensionsDirectory).eachDir { f -> + includeBuild f.path + } +} \ No newline at end of file diff --git a/src/main/java/com/warxim/booleanexpressioninterpreter/AndExpression.java b/src/main/java/com/warxim/booleanexpressioninterpreter/AndExpression.java new file mode 100644 index 0000000..e933019 --- /dev/null +++ b/src/main/java/com/warxim/booleanexpressioninterpreter/AndExpression.java @@ -0,0 +1,33 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.booleanexpressioninterpreter; + +/** Logical AND expression. */ +public final class AndExpression implements Expression { + private final Expression left; + private final Expression right; + + public AndExpression(Expression left, Expression right) { + this.left = left; + this.right = right; + } + + @Override + public boolean solve() { + return left.solve() && right.solve(); + } +} diff --git a/src/main/java/com/warxim/booleanexpressioninterpreter/BiPredicateExpression.java b/src/main/java/com/warxim/booleanexpressioninterpreter/BiPredicateExpression.java new file mode 100644 index 0000000..009f3ae --- /dev/null +++ b/src/main/java/com/warxim/booleanexpressioninterpreter/BiPredicateExpression.java @@ -0,0 +1,61 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.booleanexpressioninterpreter; + +import java.util.function.BiPredicate; + +/** + * BiPredicate expression uses BiPredicate for solve method. Result of BiPredicate is cached until + * new parameters are provided. + */ +public class BiPredicateExpression implements Expression { + private final BiPredicate predicate; + + private boolean value; + private boolean cached; + private T firstParameter; + private U secondParameter; + + public BiPredicateExpression(BiPredicate predicate) { + this.predicate = predicate; + cached = false; + } + + public BiPredicateExpression(BiPredicate function, T firstParam, U secondParam) { + this(function); + firstParameter = firstParam; + secondParameter = secondParam; + } + + public void setParams(T firstParam, U secondParam) { + firstParameter = firstParam; + secondParameter = secondParam; + cached = false; + } + + @Override + public boolean solve() { + if (cached) { + return value; + } + + cached = true; + value = predicate.test(firstParameter, secondParameter); + + return value; + } +} diff --git a/src/main/java/com/warxim/booleanexpressioninterpreter/Expression.java b/src/main/java/com/warxim/booleanexpressioninterpreter/Expression.java new file mode 100644 index 0000000..7cb4eb8 --- /dev/null +++ b/src/main/java/com/warxim/booleanexpressioninterpreter/Expression.java @@ -0,0 +1,24 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.booleanexpressioninterpreter; + +/** Expression interface. */ +@FunctionalInterface +public interface Expression { + /** Method returning result of expression. */ + boolean solve(); +} diff --git a/src/main/java/com/warxim/booleanexpressioninterpreter/ExpressionParser.java b/src/main/java/com/warxim/booleanexpressioninterpreter/ExpressionParser.java new file mode 100644 index 0000000..796a3de --- /dev/null +++ b/src/main/java/com/warxim/booleanexpressioninterpreter/ExpressionParser.java @@ -0,0 +1,228 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.booleanexpressioninterpreter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * ExpressionParser parses expressions from string and creates object structure for faster solving. + */ +public final class ExpressionParser { + private ExpressionParser() {} + + /** + * Adds spaces to the expression and unites brackets for parser. (This method is automatically + * called before parsing, so there is no need to call it manually before parsing.) + * + * @throws InvalidExpressionException + */ + public static String prepare(String expression) throws InvalidExpressionException { + if (expression.length() == 0) { + return expression; + } + + StringBuilder builder = new StringBuilder(); + int last = expression.length() - 1; + + for (int i = 0; i < last; ++i) { + char c = unifySymbol(expression.charAt(i)); + char nextC = unifySymbol(expression.charAt(i + 1)); + + if (c > '/' && c < ':') { // Number + builder.append(c); + + // Next is digit - skip space appending. + if (nextC > '/' && nextC < ':') { + continue; + } + } else if (c == '&' || c == '|' || c == '^' || c == '(' || c == ')' || c == '!') { + builder.append(c); + } else if (c != ' ') { + throw new InvalidExpressionException("Expression contains invalid character '" + c + "'!"); + } + + // Append space. + if (nextC != ' ') { + builder.append(' '); + } + } + builder.append(unifySymbol(expression.charAt(last))); + + return builder.toString().trim(); + } + + /** + * Parses index from string with specified index limit (number of first non-existing index). + * + * @throws InvalidExpressionException (index >= size) + */ + private static int parseIndex(String index, int limit) throws InvalidExpressionException { + int l = Integer.parseInt(index); + + if (l >= limit) { + throw new InvalidExpressionException("Expression contains invalid index (" + index + ")!"); + } + + return l; + } + + /** + * Parses boolean expression from string. + * + * @throws InvalidExpressionException + */ + public static Expression parse(String expression, Expression[] parameters) + throws InvalidExpressionException { + // Prepare expression for parsing. + expression = prepare(expression); + + // Create list and fill it with parameters. + List list = new ArrayList<>(Arrays.asList(parameters)); + + // Simplify until simplified. + do { + int previousLength = expression.length(); + + String[] parts = expression.split(" "); + + int end = parts.length - 2; + + // Loop through expression parts. + for (int i = 0; i <= end; ++i) { + String left = parts[i]; + String middle = parts[i + 1]; + + // NOT syntax. + if ("!".equals(left)) { + if (isIndex(middle)) { + // Save new expression to list. + list.add(new NotExpression(list.get(parseIndex(middle, list.size())))); + + // Replace !0 with 1. + expression = expression.replace("! " + middle, String.valueOf(list.size() - 1)); + + // Replace following number with new one (negated). + parts[i + 1] = String.valueOf(list.size() - 1); + } + + continue; + } + + // Are we near parts end? + if (i + 1 > end) { + continue; + } + + // Load right parts. + String right = parts[i + 2]; + + // AND / OR / XOR syntax. + if (isIndex(left) && isOperator(middle) && isIndex(right)) { + + // Save new expression to list. + list.add(createExpression(middle, list.get(parseIndex(left, list.size())), + list.get(parseIndex(right, list.size())))); + + // Replace 0 & 1 with 2. + expression = expression.replace(left + ' ' + middle + ' ' + right, + String.valueOf(list.size() - 1)); + + // Change the right value to new calculated value. + parts[i + 2] = String.valueOf(list.size() - 1); + + // Move to next value (operator) -> loop will move us from the operator to the next value. + ++i; + } + } + + // Replace all ( n ) with n. + expression = expression.replaceAll("\\( ([0-9]+) \\)", "$1"); + + // Is expression optimized? + if (isIndex(expression)) { + break; + } + + // If the expression has not changed, parse is stuck (invalid expression). + if (previousLength == expression.length()) { + throw new InvalidExpressionException( + "Could not parse expression! Please check if the expression is valid!"); + } + } while (true); + + return list.get(parseIndex(expression, list.size())); + } + + /** Is given value an operator? */ + private static boolean isOperator(String str) { + return "&".equals(str) || "^".equals(str) || "|".equals(str); + } + + /** Is given value an index? */ + private static boolean isIndex(String str) { + if (str == null) { + return false; + } + + int length = str.length(); + if (length == 0) { + return false; + } + + // Check if string contains only numeric characters. + for (int i = 0; i < length; i++) { + char c = str.charAt(i); + if (c <= '/' || c >= ':') { + return false; + } + } + + return true; + } + + /** Returns expression by given type. */ + private static Expression createExpression(String type, Expression a, Expression b) { + if ("|".equals(type)) { + return new OrExpression(a, b); + } + + if ("&".equals(type)) { + return new AndExpression(a, b); + } + + return new XorExpression(a, b); + } + + /** Unifies symbol. */ + private static char unifySymbol(char symbol) { + switch (symbol) { + case '{': + case '[': + return '('; + case '}': + case ']': + return ')'; + case '\t': + case '\n': + return ' '; + default: + return symbol; + } + } +} diff --git a/src/main/java/com/warxim/booleanexpressioninterpreter/InvalidExpressionException.java b/src/main/java/com/warxim/booleanexpressioninterpreter/InvalidExpressionException.java new file mode 100644 index 0000000..b6b0e39 --- /dev/null +++ b/src/main/java/com/warxim/booleanexpressioninterpreter/InvalidExpressionException.java @@ -0,0 +1,26 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.booleanexpressioninterpreter; + +/** Invalid expression exception. */ +public final class InvalidExpressionException extends Exception { + private static final long serialVersionUID = 1L; + + public InvalidExpressionException(String message) { + super(message); + } +} diff --git a/src/main/java/com/warxim/booleanexpressioninterpreter/NotExpression.java b/src/main/java/com/warxim/booleanexpressioninterpreter/NotExpression.java new file mode 100644 index 0000000..198529b --- /dev/null +++ b/src/main/java/com/warxim/booleanexpressioninterpreter/NotExpression.java @@ -0,0 +1,31 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.booleanexpressioninterpreter; + +/** Logical NOT expression. */ +public final class NotExpression implements Expression { + private final Expression expression; + + public NotExpression(Expression expression) { + this.expression = expression; + } + + @Override + public boolean solve() { + return !expression.solve(); + } +} diff --git a/src/main/java/com/warxim/booleanexpressioninterpreter/OrExpression.java b/src/main/java/com/warxim/booleanexpressioninterpreter/OrExpression.java new file mode 100644 index 0000000..c763f92 --- /dev/null +++ b/src/main/java/com/warxim/booleanexpressioninterpreter/OrExpression.java @@ -0,0 +1,33 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.booleanexpressioninterpreter; + +/** Logical OR expression. */ +public final class OrExpression implements Expression { + private final Expression left; + private final Expression right; + + public OrExpression(Expression left, Expression right) { + this.left = left; + this.right = right; + } + + @Override + public boolean solve() { + return left.solve() || right.solve(); + } +} diff --git a/src/main/java/com/warxim/booleanexpressioninterpreter/PredicateExpression.java b/src/main/java/com/warxim/booleanexpressioninterpreter/PredicateExpression.java new file mode 100644 index 0000000..afb1321 --- /dev/null +++ b/src/main/java/com/warxim/booleanexpressioninterpreter/PredicateExpression.java @@ -0,0 +1,59 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.booleanexpressioninterpreter; + +import java.util.function.Predicate; + +/** + * Predicate expression uses Predicate for solve method. Result of Predicate is cached until new + * parameter is provided. + */ +public class PredicateExpression implements Expression { + private final Predicate predicate; + + private boolean value; + private boolean cached; + private T parameter; + + public PredicateExpression(Predicate predicate) { + this.predicate = predicate; + cached = false; + } + + public PredicateExpression(Predicate function, T param) { + this(function); + parameter = param; + } + + /** Sets predicate parameter. */ + public void setParam(T param) { + parameter = param; + cached = false; + } + + @Override + public boolean solve() { + if (cached) { + return value; + } + + cached = true; + value = predicate.test(parameter); + + return value; + } +} diff --git a/src/main/java/com/warxim/booleanexpressioninterpreter/VariableExpression.java b/src/main/java/com/warxim/booleanexpressioninterpreter/VariableExpression.java new file mode 100644 index 0000000..1c97cf7 --- /dev/null +++ b/src/main/java/com/warxim/booleanexpressioninterpreter/VariableExpression.java @@ -0,0 +1,36 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.booleanexpressioninterpreter; + +/** Variable expression. */ +public final class VariableExpression implements Expression { + private boolean expression; + + public VariableExpression(boolean expression) { + this.expression = expression; + } + + /** Sets value of expression. */ + public void setValue(boolean expression) { + this.expression = expression; + } + + @Override + public boolean solve() { + return expression; + } +} diff --git a/src/main/java/com/warxim/booleanexpressioninterpreter/XorExpression.java b/src/main/java/com/warxim/booleanexpressioninterpreter/XorExpression.java new file mode 100644 index 0000000..8506459 --- /dev/null +++ b/src/main/java/com/warxim/booleanexpressioninterpreter/XorExpression.java @@ -0,0 +1,33 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.booleanexpressioninterpreter; + +/** Logical XOR expression. */ +public final class XorExpression implements Expression { + private final Expression left; + private final Expression right; + + public XorExpression(Expression left, Expression right) { + this.left = left; + this.right = right; + } + + @Override + public boolean solve() { + return left.solve() ^ right.solve(); + } +} diff --git a/src/main/java/com/warxim/petep/Bundle.java b/src/main/java/com/warxim/petep/Bundle.java new file mode 100644 index 0000000..aa63c89 --- /dev/null +++ b/src/main/java/com/warxim/petep/Bundle.java @@ -0,0 +1,178 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep; + +import java.io.File; +import com.warxim.petep.bootstrap.CommandLineArguments; +import com.warxim.petep.common.Constant; +import com.warxim.petep.common.ContextType; +import com.warxim.petep.configuration.ExtensionsLoader; +import com.warxim.petep.configuration.ExtensionsSaver; +import com.warxim.petep.configuration.ModulesLoader; +import com.warxim.petep.configuration.ModulesSaver; +import com.warxim.petep.configuration.ProjectLoader; +import com.warxim.petep.configuration.ProjectSaver; +import com.warxim.petep.core.PetepManager; +import com.warxim.petep.core.listener.PetepListenerManager; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.extension.ExtensionManager; +import com.warxim.petep.helper.DefaultExtensionHelper; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactoryManager; +import com.warxim.petep.interceptor.module.InterceptorModuleContainer; +import com.warxim.petep.project.Project; +import com.warxim.petep.proxy.factory.ProxyFactoryModuleManager; +import com.warxim.petep.proxy.module.ProxyModuleContainer; +import com.warxim.petep.util.FileUtils; + +/** Singleton for PETEP assets. */ +public final class Bundle { + /** Singleton instance. */ + private static Bundle instance; + + /* + * DATA + */ + private String projectPath; + private Project project; + private ContextType contextType; + + /* + * MANAGERS + */ + private ExtensionManager extensionManager; + private ProxyFactoryModuleManager proxyModuleFactoryManager; + private InterceptorModuleFactoryManager interceptorModuleFactoryManager; + private PetepListenerManager petepListenerManager; + private PetepManager petepManager; + + private Bundle() {} + + public static Bundle getInstance() { + if (instance == null) { + instance = new Bundle(); + } + + return instance; + } + + /** Loads project and managers. */ + public void load(CommandLineArguments arguments) throws ConfigurationException { + contextType = arguments.getContextType(); + projectPath = arguments.getProjectPath(); + + String configDirectory = + FileUtils.getProjectFileAbsolutePath(Constant.PROJECT_CONFIG_DIRECTORY) + File.separator; + + project = ProjectLoader.load(configDirectory + Constant.PROJECT_CONFIG_FILE); + + // Create managers. + extensionManager = new ExtensionManager( + ExtensionsLoader.load(configDirectory + Constant.EXTENSIONS_CONFIG_FILE)); + proxyModuleFactoryManager = new ProxyFactoryModuleManager(); + interceptorModuleFactoryManager = new InterceptorModuleFactoryManager(); + petepListenerManager = new PetepListenerManager(); + + // Init extensions using default extension helper. + extensionManager.init(new DefaultExtensionHelper(this)); + + // Load proxies. + ProxyModuleContainer proxyModuleContainer = new ProxyModuleContainer(ModulesLoader + .load(configDirectory + Constant.PROXIES_CONFIG_FILE, proxyModuleFactoryManager)); + + // Load interceptor module managers. + InterceptorModuleContainer interceptorModuleContainerC2S = new InterceptorModuleContainer( + ModulesLoader.load(configDirectory + Constant.INTERCEPTORS_C2S_CONFIG_FILE, + interceptorModuleFactoryManager)); + + InterceptorModuleContainer interceptorModuleContainerS2C = new InterceptorModuleContainer( + ModulesLoader.load(configDirectory + Constant.INTERCEPTORS_S2C_CONFIG_FILE, + interceptorModuleFactoryManager)); + + // Create PETEP manager. + petepManager = new PetepManager(proxyModuleContainer, interceptorModuleContainerC2S, + interceptorModuleContainerS2C, petepListenerManager); + } + + /** Saves project, extensions and configuration. */ + public void save() throws ConfigurationException { + String configDirectory = + FileUtils.getProjectFileAbsolutePath(Constant.PROJECT_CONFIG_DIRECTORY) + File.separator; + + ProjectSaver.save(configDirectory + Constant.PROJECT_CONFIG_FILE, project); + + ExtensionsSaver.save(configDirectory + Constant.EXTENSIONS_CONFIG_FILE, + extensionManager.getList()); + + ModulesSaver.save(configDirectory + Constant.PROXIES_CONFIG_FILE, + petepManager.getProxyModuleContainer().getList()); + + ModulesSaver.save(configDirectory + Constant.INTERCEPTORS_C2S_CONFIG_FILE, + petepManager.getInterceptorModuleContainerC2S().getList()); + + ModulesSaver.save(configDirectory + Constant.INTERCEPTORS_S2C_CONFIG_FILE, + petepManager.getInterceptorModuleContainerS2C().getList()); + } + + /* + * GETTERS + */ + public Project getProject() { + return project; + } + + public String getProjectPath() { + return projectPath; + } + + public ContextType getContextType() { + return contextType; + } + + public ExtensionManager getExtensionManager() { + return extensionManager; + } + + public ProxyModuleContainer getProxyModuleContainer() { + return petepManager.getProxyModuleContainer(); + } + + /** Returns interceptor module container in direction C2S. (Client -> Server) */ + public InterceptorModuleContainer getInterceptorModuleContainerC2S() { + return petepManager.getInterceptorModuleContainerC2S(); + } + + /** Returns interceptor module container in direction S2C. (Client <- Server) */ + public InterceptorModuleContainer getInterceptorModuleContainerS2C() { + return petepManager.getInterceptorModuleContainerS2C(); + } + + public ProxyFactoryModuleManager getProxyModuleFactoryManager() { + return proxyModuleFactoryManager; + } + + public InterceptorModuleFactoryManager getInterceptorModuleFactoryManager() { + return interceptorModuleFactoryManager; + } + + public PetepListenerManager getPetepListenerManager() { + return petepListenerManager; + } + + public PetepManager getPetepManager() { + return petepManager; + } +} diff --git a/src/main/java/com/warxim/petep/Main.java b/src/main/java/com/warxim/petep/Main.java new file mode 100644 index 0000000..133dccd --- /dev/null +++ b/src/main/java/com/warxim/petep/Main.java @@ -0,0 +1,73 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep; + +import java.util.logging.Logger; +import com.warxim.petep.bootstrap.CommandLineArguments; +import com.warxim.petep.bootstrap.CommandLineBoostrap; +import com.warxim.petep.bootstrap.GuiBootstrap; +import com.warxim.petep.bootstrap.PetepBootstrap; +import com.warxim.petep.common.ContextType; +import com.warxim.petep.exception.CommandLineArgumentsException; +import com.warxim.petep.wizard.PetepWizard; +import javafx.application.Application; + +/** Application main class. */ +public final class Main { + private Main() {} + + public static void main(final String... args) { + if (args.length == 0) { + runWizard(); + } else { + runPetep(args); + } + } + + /** Runs PETEP project with specified arguments. */ + public static void runPetep(final String... args) { + CommandLineArguments arguments; + + // Parse arguments from command line. + try { + arguments = new CommandLineArguments(args); + } catch (CommandLineArgumentsException e) { + Logger.getGlobal().severe(e.getMessage()); + Logger.getGlobal().info(CommandLineArguments.HELP); + return; + } + + // Choose bootstrap type. + PetepBootstrap bootstrap; + if (arguments.getContextType() == ContextType.GUI) { + bootstrap = new GuiBootstrap(arguments); + } else { + bootstrap = new CommandLineBoostrap(arguments); + } + + if (!bootstrap.start()) { + Logger.getGlobal().severe("PETEP start failed!"); + } + } + + /** Runs project wizard. */ + public static void runWizard() { + Logger.getGlobal().info("Running PETEP wizard."); + + new Thread(() -> Application.launch(PetepWizard.class)).start(); + } +} diff --git a/src/main/java/com/warxim/petep/bootstrap/CommandLineArguments.java b/src/main/java/com/warxim/petep/bootstrap/CommandLineArguments.java new file mode 100644 index 0000000..53dacbc --- /dev/null +++ b/src/main/java/com/warxim/petep/bootstrap/CommandLineArguments.java @@ -0,0 +1,83 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.bootstrap; + +import com.warxim.petep.common.ContextType; +import com.warxim.petep.exception.CommandLineArgumentsException; + +/** Command line arguments. */ +public final class CommandLineArguments { + private final String[] arguments; + private final String projectPath; + private ContextType contextType; + private boolean fromWizard; + + public static final String HELP = "petep project_dir [--nogui]"; + + /** + * Command line arguments constructor + * + * @param arguments CMD arguments from main method + */ + public CommandLineArguments(String[] arguments) throws CommandLineArgumentsException { + if (arguments.length < 1) { + throw new CommandLineArgumentsException("Not enough parameters!"); + } + + this.arguments = arguments; + + // Use the first argument as project path. + projectPath = arguments[0]; + + // Detect context type and whether the application starts from wizard. + contextType = ContextType.GUI; + fromWizard = false; + + for (int i = 1; i < arguments.length; ++i) { + String argument = arguments[i].toLowerCase(); + + if ("--nogui".equals(argument)) { + contextType = ContextType.COMMAND_LINE; + } else if ("--from-wizard".equals(argument)) { + fromWizard = true; + } + } + } + + /** Returns context type of PETEP (GUI / COMMAND_LINE). */ + public ContextType getContextType() { + return contextType; + } + + /** Returns command line arguments. */ + public String[] getArguments() { + return arguments; + } + + /** Returns project path. */ + public String getProjectPath() { + return projectPath; + } + + /** + * Returns true if project is started from wizard. (JavaFX application cannot be created multiple + * times.) + */ + public boolean isFromWizard() { + return fromWizard; + } +} diff --git a/src/main/java/com/warxim/petep/bootstrap/CommandLineBoostrap.java b/src/main/java/com/warxim/petep/bootstrap/CommandLineBoostrap.java new file mode 100644 index 0000000..c410c5e --- /dev/null +++ b/src/main/java/com/warxim/petep/bootstrap/CommandLineBoostrap.java @@ -0,0 +1,106 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.bootstrap; + +import java.util.Scanner; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.Bundle; +import com.warxim.petep.core.PetepManager; +import com.warxim.petep.core.PetepState; +import com.warxim.petep.exception.ConfigurationException; + +/** Bootstrap for command line mode. */ +public final class CommandLineBoostrap extends PetepBootstrap { + public CommandLineBoostrap(CommandLineArguments arguments) { + super(arguments); + } + + @Override + public boolean start() { + if (!super.start()) { + return false; + } + + Logger.getGlobal().info("Starting PETEP without GUI."); + + Scanner scanner = new Scanner(System.in); + PetepManager petepManager = Bundle.getInstance().getPetepManager(); + boolean running = true; + + while (running) { + // Start PETEP. + petepManager.start(); + + // Run input loop. + running = runInputLoop(scanner); + + // Stop PETEP. + petepManager.stop(); + + // Wait till the PETEP core stops, so that it can start again. + waitForPetepTermination(petepManager); + } + + // Save PETEP. (Saving stores etc.) + try { + Bundle.getInstance().save(); + } catch (ConfigurationException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception occured -> ", e); + return false; + } + + return true; + } + + /** Returns true if PETEP should continue running. */ + private static boolean runInputLoop(Scanner scanner) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + + switch (line) { + // Stop PETEP. + case "stop": + case "quit": + case "exit": + case "shutdown": + return false; + + // Restart PETEP. + case "restart": + return true; + + // Show help. + default: + Logger.getGlobal().severe("Unknown command! Use 'stop' or 'restart'!"); + } + } + return false; + } + + /** Waits till the PETEP core stops. */ + private static void waitForPetepTermination(PetepManager petepManager) { + while (petepManager.getState() != PetepState.STOPPED) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // Interrupted. + break; + } + } + } +} diff --git a/src/main/java/com/warxim/petep/bootstrap/GuiBootstrap.java b/src/main/java/com/warxim/petep/bootstrap/GuiBootstrap.java new file mode 100644 index 0000000..a303091 --- /dev/null +++ b/src/main/java/com/warxim/petep/bootstrap/GuiBootstrap.java @@ -0,0 +1,56 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.bootstrap; + +import java.util.logging.Logger; +import com.warxim.petep.gui.GuiBundle; +import com.warxim.petep.gui.PetepGui; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.stage.Stage; + +/** Bootstrap for GUI mode. */ +public final class GuiBootstrap extends PetepBootstrap { + public GuiBootstrap(CommandLineArguments arguments) { + super(arguments); + } + + @Override + public boolean start() { + if (!super.start()) { + return false; + } + + Logger.getGlobal().info("Starting PETEP with GUI."); + + if (arguments.isFromWizard()) { + // Run PETEP using existing Application instance. + Platform.runLater(() -> new PetepGui().start(new Stage())); + + // Re-enable implicit exit. + Platform.runLater(() -> Platform.setImplicitExit(true)); + } else { + // Run PETEP using new Application instance. + new Thread(() -> Application.launch(PetepGui.class)).start(); + } + + Dialogs.setDefaultIcon(GuiBundle.getInstance().getPetepIcon()); + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/bootstrap/PetepBootstrap.java b/src/main/java/com/warxim/petep/bootstrap/PetepBootstrap.java new file mode 100644 index 0000000..1ac2638 --- /dev/null +++ b/src/main/java/com/warxim/petep/bootstrap/PetepBootstrap.java @@ -0,0 +1,62 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.bootstrap; + +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.Bundle; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.util.FileUtils; + +/** Super class for bootstraps */ +public abstract class PetepBootstrap { + protected CommandLineArguments arguments; + + /** + * PetepBootstrap constructor. + * + * @param arguments arguments + */ + public PetepBootstrap(CommandLineArguments arguments) { + this.arguments = arguments; + } + + /** + * Starts PETEP project (loads assets etc. + * + * @return true if start was successful + */ + public boolean start() { + try { + // Initialize utils. + FileUtils.setProjectDirectory( + FileUtils.getApplicationFileAbsolutePath(arguments.getProjectPath())); + + // Load PETEP bundle. + Bundle.getInstance().load(arguments); + + Logger.getGlobal() + .log(Level.INFO, () -> "Loaded project " + Bundle.getInstance().getProject().getName() + + " (" + arguments.getProjectPath() + ")!"); + + return true; + } catch (ConfigurationException e) { + Logger.getGlobal().log(Level.SEVERE, "Project configuration exception occured!", e); + return false; + } + } +} diff --git a/src/main/java/com/warxim/petep/common/Constant.java b/src/main/java/com/warxim/petep/common/Constant.java new file mode 100644 index 0000000..cbbfdd2 --- /dev/null +++ b/src/main/java/com/warxim/petep/common/Constant.java @@ -0,0 +1,63 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.common; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import com.warxim.petep.extension.PetepAPI; + +/** Static class containing important constants. */ +@PetepAPI +public final class Constant { + // PETEP version + public static final String VERSION = "1.2.1"; + + // PETEP web + public static final String WEB = "http://petep.warxim.com/"; + + // Charset + public static final Charset DEFAULT_CHARSET = StandardCharsets.ISO_8859_1; + + // Configuration files + public static final String PROJECT_CONFIG_DIRECTORY = "conf"; + public static final String PROJECT_CONFIG_FILE = "project.json"; + public static final String EXTENSIONS_CONFIG_FILE = "extensions.json"; + public static final String PROXIES_CONFIG_FILE = "proxies.json"; + public static final String INTERCEPTORS_C2S_CONFIG_FILE = "interceptors-C2S.json"; + public static final String INTERCEPTORS_S2C_CONFIG_FILE = "interceptors-S2C.json"; + + // Internal extensions + public static final List INTERNAL_EXTENSIONS = + Collections.unmodifiableList(Arrays.asList("logger", "tcp", "http", "external_http_proxy", + "test", "connection_view", "tagger", "catcher", "modifier")); + + // Configuration items + public static final String CONFIG_ITEM_FACTORY = "factory"; + public static final String CONFIG_ITEM_ENABLED = "enabled"; + public static final String CONFIG_ITEM_STORE = "store"; + public static final String CONFIG_ITEM_CONFIG = "config"; + public static final String CONFIG_ITEM_CODE = "code"; + public static final String CONFIG_ITEM_PATH = "path"; + public static final String CONFIG_ITEM_NAME = "name"; + public static final String CONFIG_ITEM_DESCRIPTION = "description"; + + /** No need for instance creation. */ + private Constant() {} +} diff --git a/src/main/java/com/warxim/petep/common/ContextType.java b/src/main/java/com/warxim/petep/common/ContextType.java new file mode 100644 index 0000000..dd348a0 --- /dev/null +++ b/src/main/java/com/warxim/petep/common/ContextType.java @@ -0,0 +1,25 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.common; + +import com.warxim.petep.extension.PetepAPI; + +/** Context type represents the type of current PETEP context (GUI / Command Line). */ +@PetepAPI +public enum ContextType { + COMMAND_LINE, GUI +} diff --git a/src/main/java/com/warxim/petep/configuration/ExtensionsLoader.java b/src/main/java/com/warxim/petep/configuration/ExtensionsLoader.java new file mode 100644 index 0000000..526eacc --- /dev/null +++ b/src/main/java/com/warxim/petep/configuration/ExtensionsLoader.java @@ -0,0 +1,194 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.configuration; + +import java.io.FileReader; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.NoSuchFileException; +import java.util.ArrayList; +import java.util.List; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; +import com.warxim.petep.common.Constant; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.exception.ExtensionLoadException; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.internal.catcher.CatcherExtension; +import com.warxim.petep.extension.internal.connection_view.ConnectionViewExtension; +import com.warxim.petep.extension.internal.external_http_proxy.EHTTPPExtension; +import com.warxim.petep.extension.internal.http.HttpExtension; +import com.warxim.petep.extension.internal.logger.LoggerExtension; +import com.warxim.petep.extension.internal.modifier.ModifierExtension; +import com.warxim.petep.extension.internal.tagger.TaggerExtension; +import com.warxim.petep.extension.internal.tcp.TcpExtension; +import com.warxim.petep.extension.internal.test.TestExtension; +import com.warxim.petep.persistence.Configurable; +import com.warxim.petep.persistence.Storable; +import com.warxim.petep.util.ExtensionUtils; +import com.warxim.petep.util.FileUtils; + +/** Static class for loading extensions. */ +public final class ExtensionsLoader { + private ExtensionsLoader() {} + + /** Loads extensions from specified path. */ + public static List load(String path) throws ConfigurationException { + // Read configuration from specified path. + try (JsonReader reader = new JsonReader(new FileReader(path))) { + JsonArray list = JsonParser.parseReader(reader).getAsJsonArray(); + ArrayList extensions = new ArrayList<>(list.size()); + + for (int i = 0; i < list.size(); ++i) { + try { + JsonObject extension = list.get(i).getAsJsonObject(); + + // Load extension and add it to list. + extensions.add(loadExtension(extension.get(Constant.CONFIG_ITEM_PATH).getAsString(), + extension.get(Constant.CONFIG_ITEM_STORE), + extension.get(Constant.CONFIG_ITEM_CONFIG))); + } catch (ExtensionLoadException e) { + throw new ConfigurationException("Could not load extension!", e); + } + } + + return extensions; + } catch (JsonParseException e) { + throw new ConfigurationException("Could not parse project configuration!", e); + } catch (NoSuchFileException e) { + throw new ConfigurationException("Could not found project configuration!", e); + } catch (IOException e) { + throw new ConfigurationException("Could not load project configuration!", e); + } + } + + /** + * Loads specified extension by given name (internal or external) and hands over the + * configuration. + */ + private static Extension loadExtension(String path, JsonElement store, JsonElement config) + throws ExtensionLoadException { + Extension extension; + + switch (path) { + case "logger": + extension = new LoggerExtension("logger"); + break; + case "test": + extension = new TestExtension("test"); + break; + case "external_http_proxy": + extension = new EHTTPPExtension("external_http_proxy"); + break; + case "tcp": + extension = new TcpExtension("tcp"); + break; + case "tagger": + extension = new TaggerExtension("tagger"); + break; + case "catcher": + extension = new CatcherExtension("catcher"); + break; + case "connection_view": + extension = new ConnectionViewExtension("connection_view"); + break; + case "http": + extension = new HttpExtension("http"); + break; + case "modifier": + extension = new ModifierExtension("modifier"); + break; + default: + extension = loadExternalExtension(path); + } + + loadExtensionConfig(extension, config); + loadExtensionStore(extension, store); + + return extension; + } + + /** + * Decides if extension expects store and hands it over. + * + * @throws ExtensionLoadException + */ + private static void loadExtensionStore(Extension extension, JsonElement store) { + // No store in json. + if (store == null) { + return; + } + + // Get store type using reflections. + Type storeType = ExtensionUtils.getStoreType(extension); + if (storeType == null) { + return; + } + + // Deserialize store to expected type and give the to the extension. + ((Storable) extension).loadStore(new GsonBuilder().create().fromJson(store, storeType)); + } + + /** + * Decides if extension expects config and hands it over. + * + * @throws ExtensionLoadException + */ + private static void loadExtensionConfig(Extension extension, JsonElement config) { + // No config in json. + if (config == null) { + return; + } + + // Get config type using reflections. + Type configType = ExtensionUtils.getConfigType(extension); + if (configType == null) { + return; + } + + // Deserialize config to expected type and give the config to the extension. + ((Configurable) extension) + .loadConfig(new GsonBuilder().create().fromJson(config, configType)); + } + + /** Loads specified .jar file extension. */ + private static Extension loadExternalExtension(String path) throws ExtensionLoadException { + try { + URLClassLoader classLoader = + new URLClassLoader(new URL[] {FileUtils.getApplicationFile(path).toURI().toURL()}); + + // Create instance of extension class. + return (Extension) Class.forName("petep.PetepExtension", true, classLoader) + .getConstructor(String.class) + .newInstance(path); + } catch (MalformedURLException | InstantiationException | IllegalAccessException + | ClassNotFoundException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { + throw new ExtensionLoadException( + "Extension '" + path + "' could not be loaded -> " + e.toString(), e); + } + } +} diff --git a/src/main/java/com/warxim/petep/configuration/ExtensionsSaver.java b/src/main/java/com/warxim/petep/configuration/ExtensionsSaver.java new file mode 100644 index 0000000..6038fd5 --- /dev/null +++ b/src/main/java/com/warxim/petep/configuration/ExtensionsSaver.java @@ -0,0 +1,80 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.configuration; + +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.nio.file.NoSuchFileException; +import java.util.Collection; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.stream.JsonWriter; +import com.warxim.petep.common.Constant; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.persistence.Configurable; +import com.warxim.petep.persistence.Storable; +import com.warxim.petep.util.ExtensionUtils; + +/** Static class for saving extensions. */ +public final class ExtensionsSaver { + + private ExtensionsSaver() {} + + /** Saves extensions to specified path. */ + public static void save(String path, Collection extensions) + throws ConfigurationException { + // Enable pretty printing. + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + JsonArray list = new JsonArray(extensions.size()); + + for (Extension extension : extensions) { + JsonObject object = new JsonObject(); + + // Save extension path. + object.addProperty(Constant.CONFIG_ITEM_PATH, extension.getPath()); + + // Save extension store. + Type storeType = ExtensionUtils.getStoreType(extension); + if (storeType != null) { + object.add(Constant.CONFIG_ITEM_STORE, + gson.toJsonTree(((Storable) extension).saveStore(), storeType)); + } + + // Save extension config. + Type configType = ExtensionUtils.getConfigType(extension); + if (configType != null) { + object.add(Constant.CONFIG_ITEM_CONFIG, + gson.toJsonTree(((Configurable) extension).saveConfig(), configType)); + } + + list.add(object); + } + + // Write json to specified path. + try (JsonWriter writer = gson.newJsonWriter(new FileWriter(path))) { + gson.toJson(list, writer); + } catch (NoSuchFileException e) { + throw new ConfigurationException("Could not found extensions configuration!", e); + } catch (IOException e) { + throw new ConfigurationException("Could not save extensions configuration!", e); + } + } +} diff --git a/src/main/java/com/warxim/petep/configuration/ModulesLoader.java b/src/main/java/com/warxim/petep/configuration/ModulesLoader.java new file mode 100644 index 0000000..e1f3d2f --- /dev/null +++ b/src/main/java/com/warxim/petep/configuration/ModulesLoader.java @@ -0,0 +1,129 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.configuration; + +import java.io.FileReader; +import java.io.IOException; +import java.lang.reflect.Type; +import java.nio.file.NoSuchFileException; +import java.util.ArrayList; +import java.util.List; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; +import com.warxim.petep.common.Constant; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.module.Module; +import com.warxim.petep.module.ModuleFactory; +import com.warxim.petep.module.ModuleFactoryManager; +import com.warxim.petep.persistence.Configurable; +import com.warxim.petep.persistence.Storable; +import com.warxim.petep.util.ExtensionUtils; + +/** Static class for loading modules. */ +public final class ModulesLoader { + private ModulesLoader() {} + + /** Loads modules from specified configuration. */ + public static > List load( + String path, + ModuleFactoryManager> moduleFactoryManager) + throws ConfigurationException { + try (JsonReader reader = new JsonReader(new FileReader(path))) { + JsonArray list = JsonParser.parseReader(reader).getAsJsonArray(); + ArrayList modules = new ArrayList<>(list.size()); + + for (int i = 0; i < list.size(); ++i) { + // Load module and add it to list. + modules.add(loadModule(list.get(i).getAsJsonObject(), moduleFactoryManager)); + } + + return modules; + } catch (JsonParseException e) { + throw new ConfigurationException("Could not parse configuration! (" + path + ")", e); + } catch (NoSuchFileException e) { + throw new ConfigurationException("Could not find configuration! (" + path + ")", e); + } catch (IOException e) { + throw new ConfigurationException("Could not load configuration! (" + path + ")", e); + } + } + + /** Loads module from json object using module factory manager. */ + private static > M loadModule( + JsonObject json, + ModuleFactoryManager> moduleFactoryManager) + throws ConfigurationException { + // Get module using factory code from json. + ModuleFactory factory = + moduleFactoryManager.getModuleFactory(json.get(Constant.CONFIG_ITEM_FACTORY).getAsString()); + + // If factory has not been found, we cannot load module. + if (factory == null) { + throw new ConfigurationException("Module factory '" + + json.get(Constant.CONFIG_ITEM_FACTORY).getAsString() + "' does not exist!"); + } + + // Create module using factory. + M module = factory.createModule(json.get(Constant.CONFIG_ITEM_CODE).getAsString(), + json.get(Constant.CONFIG_ITEM_NAME).getAsString(), + json.get(Constant.CONFIG_ITEM_DESCRIPTION).getAsString(), + json.get(Constant.CONFIG_ITEM_ENABLED).getAsBoolean()); + + processConfig(module, json.get(Constant.CONFIG_ITEM_CONFIG)); + processStore(module, json.get(Constant.CONFIG_ITEM_STORE)); + + return module; + } + + /** Processes json store for module. */ + private static > void processStore(M module, JsonElement store) { + // Store does not exist. + if (store == null) { + return; + } + + // Get store type using reflections. + Type storeType = ExtensionUtils.getStoreType(module); + if (storeType == null) { + return; + } + + // Deserialize store and hand it over to module. + ((Storable) module).loadStore(new GsonBuilder().create().fromJson(store, storeType)); + } + + /** Processes json config for module. */ + private static > void processConfig(M module, JsonElement config) { + // Config does not exist. + if (config == null) { + return; + } + + // Get config type using reflections. + Type configType = ExtensionUtils.getConfigType(module); + if (configType == null) { + return; + } + + // Deserialize config and hand it over to module. + ((Configurable) module).loadConfig(new GsonBuilder().create().fromJson(config, configType)); + } +} diff --git a/src/main/java/com/warxim/petep/configuration/ModulesSaver.java b/src/main/java/com/warxim/petep/configuration/ModulesSaver.java new file mode 100644 index 0000000..b393090 --- /dev/null +++ b/src/main/java/com/warxim/petep/configuration/ModulesSaver.java @@ -0,0 +1,83 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.configuration; + +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.nio.file.NoSuchFileException; +import java.util.Collection; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.stream.JsonWriter; +import com.warxim.petep.common.Constant; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.module.Module; +import com.warxim.petep.persistence.Configurable; +import com.warxim.petep.persistence.Storable; +import com.warxim.petep.util.ExtensionUtils; + +/** Static class for saving modules. */ +public final class ModulesSaver { + private ModulesSaver() {} + + /** Saves modules to specified path. */ + public static > void save(String path, Collection modules) + throws ConfigurationException { + // Use gson with pretty printing. + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + JsonArray list = new JsonArray(modules.size()); + + for (M module : modules) { + JsonObject object = new JsonObject(); + + // Add properties to the json object. + object.addProperty(Constant.CONFIG_ITEM_CODE, module.getCode()); + object.addProperty(Constant.CONFIG_ITEM_NAME, module.getName()); + object.addProperty(Constant.CONFIG_ITEM_DESCRIPTION, module.getDescription()); + object.addProperty(Constant.CONFIG_ITEM_FACTORY, module.getFactory().getCode()); + object.addProperty(Constant.CONFIG_ITEM_ENABLED, module.isEnabled()); + + // Add store to the json object. + Type storeType = ExtensionUtils.getStoreType(module); + if (storeType != null) { + object.add(Constant.CONFIG_ITEM_STORE, + gson.toJsonTree(((Storable) module).saveStore(), storeType)); + } + + // Add config to the json object. + Type configType = ExtensionUtils.getConfigType(module); + if (configType != null) { + object.add(Constant.CONFIG_ITEM_CONFIG, + gson.toJsonTree(((Configurable) module).saveConfig(), configType)); + } + + list.add(object); + } + + // Write json to specified path. + try (JsonWriter writer = gson.newJsonWriter(new FileWriter(path))) { + gson.toJson(list, writer); + } catch (NoSuchFileException e) { + throw new ConfigurationException("Could not found configuration! (" + path + ")", e); + } catch (IOException e) { + throw new ConfigurationException("Could not save configuration! (" + path + ")", e); + } + } +} diff --git a/src/main/java/com/warxim/petep/configuration/ProjectLoader.java b/src/main/java/com/warxim/petep/configuration/ProjectLoader.java new file mode 100644 index 0000000..85113f7 --- /dev/null +++ b/src/main/java/com/warxim/petep/configuration/ProjectLoader.java @@ -0,0 +1,45 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.configuration; + +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.NoSuchFileException; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.project.Project; + +/** Static class for project loading. */ +public final class ProjectLoader { + private ProjectLoader() {} + + /** Loads project from specified path. */ + public static Project load(String path) throws ConfigurationException { + try (JsonReader reader = new JsonReader(new FileReader(path))) { + return new GsonBuilder().create().fromJson(JsonParser.parseReader(reader), Project.class); + } catch (JsonParseException e) { + throw new ConfigurationException("Could not parse project configuration!", e); + } catch (NoSuchFileException e) { + throw new ConfigurationException("Could not find project configuration!", e); + } catch (IOException e) { + throw new ConfigurationException("Could not load project configuration!", e); + } + } +} diff --git a/src/main/java/com/warxim/petep/configuration/ProjectSaver.java b/src/main/java/com/warxim/petep/configuration/ProjectSaver.java new file mode 100644 index 0000000..71649dc --- /dev/null +++ b/src/main/java/com/warxim/petep/configuration/ProjectSaver.java @@ -0,0 +1,44 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.configuration; + +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.NoSuchFileException; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.stream.JsonWriter; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.project.Project; + +/** Static class for project saving. */ +public final class ProjectSaver { + private ProjectSaver() {} + + /** Saves project to specified path. */ + public static void save(String path, Project project) throws ConfigurationException { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + try (JsonWriter writer = gson.newJsonWriter(new FileWriter(path))) { + gson.toJson(gson.toJsonTree(project), writer); + } catch (NoSuchFileException e) { + throw new ConfigurationException("Could not found project configuration!", e); + } catch (IOException e) { + throw new ConfigurationException("Could not save project configuration!", e); + } + } +} diff --git a/src/main/java/com/warxim/petep/core/PETEP.java b/src/main/java/com/warxim/petep/core/PETEP.java new file mode 100644 index 0000000..7c54514 --- /dev/null +++ b/src/main/java/com/warxim/petep/core/PETEP.java @@ -0,0 +1,230 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.core; + +import java.util.logging.Logger; +import com.warxim.petep.core.listener.PetepListener; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.helper.DefaultPetepHelper; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.module.InterceptorModuleContainer; +import com.warxim.petep.interceptor.worker.InterceptorExecutor; +import com.warxim.petep.interceptor.worker.InterceptorManager; +import com.warxim.petep.proxy.module.ProxyModuleContainer; +import com.warxim.petep.proxy.worker.ProxyExecutor; +import com.warxim.petep.proxy.worker.ProxyManager; + +/** PETEP core class. */ +public final class PETEP { + private final PetepListener listener; + private final PetepHelper helper; + private final Thread thread; + + private PetepState state; + + // Managers + private final ProxyManager proxyManager; + private final InterceptorManager interceptorManagerC2S; + private final InterceptorManager interceptorManagerS2C; + + // Executors + private final ProxyExecutor proxyExecutor; + private final InterceptorExecutor interceptorExecutorC2S; + private final InterceptorExecutor interceptorExecutorS2C; + + /** PETEP constructor. */ + public PETEP( + ProxyModuleContainer proxyModuleContainer, + InterceptorModuleContainer interceptorModuleContainerC2S, + InterceptorModuleContainer interceptorModuleContainerS2C, + PetepListener listener) { + this.listener = listener; + + // Create helper. + helper = new DefaultPetepHelper(this); + + // Create managers. + proxyManager = new ProxyManager(helper, proxyModuleContainer); + interceptorManagerC2S = new InterceptorManager(helper, interceptorModuleContainerC2S); + interceptorManagerS2C = new InterceptorManager(helper, interceptorModuleContainerS2C); + + // Create executors. + proxyExecutor = new ProxyExecutor(proxyManager); + + interceptorExecutorC2S = new InterceptorExecutor(interceptorManagerC2S, this::sendC2S); + interceptorExecutorS2C = new InterceptorExecutor(interceptorManagerS2C, this::sendS2C); + + state = PetepState.STOPPED; + + this.thread = new Thread(this::run); + } + + /** Starts PETEP. */ + public void start() { + if (state != PetepState.STOPPED) { + return; + } + + thread.start(); + } + + /** Stops PETEP. */ + public void stop() { + if (state != PetepState.STARTED) { + return; + } + + thread.interrupt(); + } + + /** Runs PETEP. */ + private void run() { + listener.beforePrepare(helper); + if (!runPrepare()) { + Logger.getGlobal().severe("PETEP failed to prepare!"); + } else { + listener.afterPrepare(helper); + + listener.beforeStart(helper); + if (!runStart()) { + Logger.getGlobal().severe("PETEP failed to start!"); + } else { + listener.afterStart(helper); + + try { + thread.join(); + } catch (InterruptedException e) { + Logger.getGlobal().info("PETEP interrupted..."); + Thread.currentThread().interrupt(); + } + } + } + + listener.beforeStop(helper); + runStop(); + listener.afterStop(helper); + } + + /** Runs prepare. */ + private boolean runPrepare() { + Logger.getGlobal().info("PETEP preparing..."); + state = PetepState.PREPARING; + + if (!proxyExecutor.prepare() || !interceptorExecutorC2S.prepare() + || !interceptorExecutorS2C.prepare()) { + return false; + } + + state = PetepState.PREPARED; + Logger.getGlobal().info("PETEP prepared..."); + + return true; + } + + /** Runs start. */ + private boolean runStart() { + Logger.getGlobal().info("PETEP starting..."); + state = PetepState.STARTING; + + if (!proxyExecutor.start()) { + return false; + } + + interceptorExecutorC2S.start(); + interceptorExecutorS2C.start(); + + state = PetepState.STARTED; + Logger.getGlobal().info("PETEP started..."); + + return true; + } + + /** Runs stop. */ + private void runStop() { + Logger.getGlobal().info("PETEP stopping..."); + state = PetepState.STOPPING; + + proxyExecutor.stop(); + interceptorExecutorC2S.stop(); + interceptorExecutorS2C.stop(); + + state = PetepState.STOPPED; + Logger.getGlobal().info("PETEP stopped..."); + } + + /** Sends PDU in direction C2S out of PETEP. (Client -> Server) */ + public void sendC2S(PDU pdu) { + pdu.getConnection().sendC2S(pdu); + } + + /** Sends PDU in direction S2C out of PETEP. (Client <- Server) */ + public void sendS2C(PDU pdu) { + pdu.getConnection().sendS2C(pdu); + } + + /** Processes PDU internally in direction C2S. (Client -> Server) */ + public void processC2S(PDU pdu) { + if (pdu.getLastInterceptor() == null) { + interceptorExecutorC2S.intercept(pdu); + } else { + interceptorExecutorC2S.intercept(pdu, pdu.getLastInterceptor().getId() + 1); + } + } + + /** Processes PDU internally in direction S2C. (Client <- Server) */ + public void processS2C(PDU pdu) { + if (pdu.getLastInterceptor() == null) { + interceptorExecutorS2C.intercept(pdu); + } else { + interceptorExecutorS2C.intercept(pdu, pdu.getLastInterceptor().getId() + 1); + } + } + + /** + * Processes PDU internally in direction C2S and start in specified interceptor. (Client -> + * Server) + */ + public void processC2S(PDU pdu, int interceptorId) { + interceptorExecutorC2S.intercept(pdu, interceptorId); + } + + /** + * Processes PDU internally in direction S2C and start in specified interceptor. (Client <- + * Server) + */ + public void processS2C(PDU pdu, int interceptorId) { + interceptorExecutorS2C.intercept(pdu, interceptorId); + } + + public PetepState getState() { + return state; + } + + public ProxyManager getProxyManager() { + return proxyManager; + } + + /** Returns interceptor manager in direction C2S. (Client -> Server) */ + public InterceptorManager getInterceptorManagerC2S() { + return interceptorManagerC2S; + } + + /** Returns interceptor manager in direction S2C. (Client <- Server) */ + public InterceptorManager getInterceptorManagerS2C() { + return interceptorManagerS2C; + } +} diff --git a/src/main/java/com/warxim/petep/core/PetepManager.java b/src/main/java/com/warxim/petep/core/PetepManager.java new file mode 100644 index 0000000..fa646a2 --- /dev/null +++ b/src/main/java/com/warxim/petep/core/PetepManager.java @@ -0,0 +1,139 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.core; + +import com.warxim.petep.core.listener.PetepListener; +import com.warxim.petep.core.listener.PetepListenerManager; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.module.InterceptorModuleContainer; +import com.warxim.petep.proxy.module.ProxyModuleContainer; + +/** + * PETEP manager allows application to start & stop PETEP and hands over the resources to the PETEP + * core. + */ +public final class PetepManager implements PetepListener { + private final ProxyModuleContainer proxyModuleContainer; + private final InterceptorModuleContainer interceptorModuleContainerC2S; + private final InterceptorModuleContainer interceptorModuleContainerS2C; + + private final PetepListenerManager petepListenerManager; + + private PETEP petep; + + public PetepManager( + ProxyModuleContainer proxyModuleManager, + InterceptorModuleContainer interceptorModuleContainerC2S, + InterceptorModuleContainer interceptorModuleContainerS2C, + PetepListenerManager petepListenerManager) { + this.proxyModuleContainer = proxyModuleManager; + this.interceptorModuleContainerC2S = interceptorModuleContainerC2S; + this.interceptorModuleContainerS2C = interceptorModuleContainerS2C; + this.petepListenerManager = petepListenerManager; + + petep = null; + + petepListenerManager.registerListener(this); + } + + /* + * CONTROL + */ + /** Creates and starts PETEP. */ + public synchronized void start() { + if (petep != null) { + return; + } + + petep = new PETEP(proxyModuleContainer, interceptorModuleContainerC2S, + interceptorModuleContainerS2C, petepListenerManager); + + petep.start(); + } + + /** Stops PETEP. */ + public synchronized void stop() { + if (petep == null) { + return; + } + + petep.stop(); + } + + /* + * GETTERS + */ + /** Returns PETEP state. */ + public synchronized PetepState getState() { + if (petep == null) { + return PetepState.STOPPED; + } + + return petep.getState(); + } + + public ProxyModuleContainer getProxyModuleContainer() { + return proxyModuleContainer; + } + + /** Returns interceptor module container for direction C2S. (Client -> Server) */ + public InterceptorModuleContainer getInterceptorModuleContainerC2S() { + return interceptorModuleContainerC2S; + } + + /** Returns interceptor module container for direction S2C. (Client <- Server) */ + public InterceptorModuleContainer getInterceptorModuleContainerS2C() { + return interceptorModuleContainerS2C; + } + + public PetepListenerManager getPetepListenerManager() { + return petepListenerManager; + } + + /* + * LISTENER + */ + @Override + public void beforePrepare(PetepHelper helper) { + // No action needed. + } + + @Override + public void afterPrepare(PetepHelper helper) { + // No action needed. + } + + @Override + public void afterStart(PetepHelper helper) { + // No action needed. + } + + @Override + public void beforeStart(PetepHelper helper) { + // No action needed. + } + + @Override + public void beforeStop(PetepHelper helper) { + // No action needed. + } + + @Override + public synchronized void afterStop(PetepHelper helper) { + petep = null; + } +} diff --git a/src/main/java/com/warxim/petep/core/PetepState.java b/src/main/java/com/warxim/petep/core/PetepState.java new file mode 100644 index 0000000..7cccf93 --- /dev/null +++ b/src/main/java/com/warxim/petep/core/PetepState.java @@ -0,0 +1,25 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.core; + +import com.warxim.petep.extension.PetepAPI; + +/** State of PETEP. */ +@PetepAPI +public enum PetepState { + PREPARING, PREPARED, STARTING, STARTED, STOPPING, STOPPED +} diff --git a/src/main/java/com/warxim/petep/core/connection/Connection.java b/src/main/java/com/warxim/petep/core/connection/Connection.java new file mode 100644 index 0000000..29fafd9 --- /dev/null +++ b/src/main/java/com/warxim/petep/core/connection/Connection.java @@ -0,0 +1,100 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.core.connection; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.core.pdu.PduQueue; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.proxy.worker.Proxy; + +/** + * Connection in PETEP proxy has to handle both connection between client and proxy and between + * proxy and server. Contains two outgoing queues that contain PDUs that should be sent in a given + * direction (C2S / S2C). + */ +@PetepAPI +public abstract class Connection { + /** Unique nummeric identifier of the connection. */ + protected final int id; + + /** Parent proxy. */ + protected final Proxy proxy; + + /** Outgoing queue in direction C2S (client -> server). */ + protected final PduQueue queueC2S; + + /** Outgoing queue in direction S2C (client <- server). */ + protected final PduQueue queueS2C; + + /** Connection constructor. */ + public Connection(int id, Proxy proxy) { + this.id = id; + this.proxy = proxy; + this.queueC2S = new PduQueue(); + this.queueS2C = new PduQueue(); + } + + public int getId() { + return id; + } + + /** Sends PDU outside the PETEP. */ + public final void send(PDU pdu) { + if (pdu.getDestination() == PduDestination.SERVER) { + queueC2S.add(pdu); + } else { + queueS2C.add(pdu); + } + } + + /** Sends PDU outside the PETEP in direction C2S (client -> server). */ + public final void sendC2S(PDU pdu) { + queueC2S.add(pdu); + } + + /** Sends PDU outside the PETEP in direction S2C (client <- server). */ + public final void sendS2C(PDU pdu) { + queueS2C.add(pdu); + } + + /** Processes PDU in PETEP core. */ + protected final void process(PDU pdu) { + proxy.getHelper().processPdu(pdu); + } + + /** About connection. */ + @Override + public String toString() { + return "Connection " + id; + } + + /** + * Starts connection. + * + *

+ * @return Returns true if the start was successful. + * + *

+ * Attention: this method should return ASAP - it should be used to create threads and then + * return immediately. + */ + public abstract boolean start(); + + /** Stops connection. */ + public abstract void stop(); +} diff --git a/src/main/java/com/warxim/petep/core/connection/ConnectionManager.java b/src/main/java/com/warxim/petep/core/connection/ConnectionManager.java new file mode 100644 index 0000000..1fe8a84 --- /dev/null +++ b/src/main/java/com/warxim/petep/core/connection/ConnectionManager.java @@ -0,0 +1,45 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.core.connection; + +import java.util.List; +import com.warxim.petep.extension.PetepAPI; + +/** + * Abstract class of connection manager that could be used by internal or external modules to work + * with connections of a given proxy. + */ +@PetepAPI +public abstract class ConnectionManager { + /** Returns connection by ID. */ + public abstract Connection get(int id); + + /** Adds connection to the connection manager. */ + public abstract boolean add(Connection connection); + + /** Removes connection from the connection manager. */ + public abstract boolean remove(Connection connection); + + /** Removes connection from the connection manager. */ + public abstract Connection remove(int id); + + /** Returns list of connections. */ + public abstract List getList(); + + /** Stops all connections. */ + public abstract void stop(); +} diff --git a/src/main/java/com/warxim/petep/core/connection/DefaultConnectionManager.java b/src/main/java/com/warxim/petep/core/connection/DefaultConnectionManager.java new file mode 100644 index 0000000..4d3df0e --- /dev/null +++ b/src/main/java/com/warxim/petep/core/connection/DefaultConnectionManager.java @@ -0,0 +1,72 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.core.connection; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import com.warxim.petep.extension.PetepAPI; + +/** Default connection manager that uses ConcurrentHashMap for connection storage. */ +@PetepAPI +public class DefaultConnectionManager extends ConnectionManager { + /** Map of connections. */ + protected final ConcurrentHashMap connections; + + /** ID of last connection. */ + private int lastId; + + public DefaultConnectionManager() { + connections = new ConcurrentHashMap<>(); + lastId = 0; + } + + @Override + public Connection get(int id) { + return connections.get(id); + } + + @Override + public boolean add(Connection connection) { + return connections.putIfAbsent(connection.getId(), connection) == null; + } + + @Override + public boolean remove(Connection connection) { + return connections.remove(connection.getId(), connection); + } + + @Override + public Connection remove(int id) { + return connections.remove(id); + } + + @Override + public List getList() { + return new ArrayList<>(connections.values()); + } + + @Override + public void stop() { + connections.values().parallelStream().forEach(Connection::stop); + } + + /** Generates new id for connection. */ + public synchronized int nextId() { + return lastId++; + } +} diff --git a/src/main/java/com/warxim/petep/core/listener/PetepListener.java b/src/main/java/com/warxim/petep/core/listener/PetepListener.java new file mode 100644 index 0000000..d849e34 --- /dev/null +++ b/src/main/java/com/warxim/petep/core/listener/PetepListener.java @@ -0,0 +1,50 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.core.listener; + +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.helper.PetepHelper; + +/** + * PETEP listener interface. Allows extensions to listen for PETEP events and also allows them to + * obtain PetepHelper. + * + *

+ * ATTENTION: Extensions should remove PetepHelper from their memory after PETEP stops, so + * that GC can collect resources. (This, of course, applies to all other resources that are + * connected to PETEP instance.) + */ +@PetepAPI +public interface PetepListener { + /** Event before prepare step is processed. */ + default void beforePrepare(PetepHelper helper) {} + + /** Event after prepare step is processed. */ + default void afterPrepare(PetepHelper helper) {} + + /** Event before start step is processed. */ + default void beforeStart(PetepHelper helper) {} + + /** Event after start step is processed. */ + default void afterStart(PetepHelper helper) {} + + /** Event before stop step is processed. */ + default void beforeStop(PetepHelper helper) {} + + /** Event after stop step is processed. */ + default void afterStop(PetepHelper helper) {} +} diff --git a/src/main/java/com/warxim/petep/core/listener/PetepListenerManager.java b/src/main/java/com/warxim/petep/core/listener/PetepListenerManager.java new file mode 100644 index 0000000..6bd5c07 --- /dev/null +++ b/src/main/java/com/warxim/petep/core/listener/PetepListenerManager.java @@ -0,0 +1,68 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.core.listener; + +import java.util.ArrayList; +import java.util.List; +import com.warxim.petep.helper.PetepHelper; + +/** Listener manager that allows modules to register their own listener. */ +public final class PetepListenerManager implements PetepListener { + private final List listeners; + + public PetepListenerManager() { + listeners = new ArrayList<>(); + } + + public void registerListener(PetepListener listener) { + listeners.add(listener); + } + + public void unregisterListener(PetepListener listener) { + listeners.remove(listener); + } + + @Override + public void beforePrepare(PetepHelper helper) { + listeners.parallelStream().forEach(listener -> listener.beforePrepare(helper)); + } + + @Override + public void afterPrepare(PetepHelper helper) { + listeners.parallelStream().forEach(listener -> listener.afterPrepare(helper)); + } + + @Override + public void beforeStart(PetepHelper helper) { + listeners.parallelStream().forEach(listener -> listener.beforeStart(helper)); + } + + @Override + public void afterStart(PetepHelper helper) { + listeners.parallelStream().forEach(listener -> listener.afterStart(helper)); + } + + @Override + public void beforeStop(PetepHelper helper) { + listeners.parallelStream().forEach(listener -> listener.beforeStop(helper)); + } + + @Override + public void afterStop(PetepHelper helper) { + listeners.parallelStream().forEach(listener -> listener.afterStop(helper)); + } +} diff --git a/src/main/java/com/warxim/petep/core/pdu/DefaultPdu.java b/src/main/java/com/warxim/petep/core/pdu/DefaultPdu.java new file mode 100644 index 0000000..09459d5 --- /dev/null +++ b/src/main/java/com/warxim/petep/core/pdu/DefaultPdu.java @@ -0,0 +1,112 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.core.pdu; + +import java.nio.charset.Charset; +import java.util.HashSet; +import java.util.Set; +import com.warxim.petep.common.Constant; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.proxy.worker.Proxy; + +/** Default PDU implementation. */ +@PetepAPI +public class DefaultPdu extends PDU { + protected byte[] buffer; + protected int size; + protected Charset charset; + + /** Default PDU implementation constructor. */ + public DefaultPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size, + Set tags) { + super(proxy, connection, destination, tags); + this.buffer = buffer; + this.size = size; + this.charset = Constant.DEFAULT_CHARSET; + } + + public DefaultPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size) { + super(proxy, connection, destination, new HashSet<>()); + this.buffer = buffer; + this.size = size; + this.charset = Constant.DEFAULT_CHARSET; + } + + /** Returns the buffer. */ + @Override + public byte[] getBuffer() { + return buffer; + } + + /** Returns size of data in the buffer. */ + @Override + public int getSize() { + return size; + } + + /** Sets the buffer and size of data inside the buffer. */ + @Override + public void setBuffer(byte[] buffer, int size) { + this.buffer = buffer; + this.size = size; + } + + /** Resizes the buffer (expands the buffer when needed, but does not shrink the buffer). */ + @Override + public void resize(int size) { + if (size <= buffer.length) { + return; + } + + byte[] newBuffer = new byte[size]; + + // Copy content of original buffer to new one. + System.arraycopy(buffer, 0, newBuffer, 0, this.size); + + buffer = newBuffer; + } + + @Override + public PDU copy() { + PDU pdu = new DefaultPdu(proxy, connection, destination, buffer.clone(), size); + + pdu.addTags(tags); + + return pdu; + } + + @Override + public Charset getCharset() { + return charset; + } + + @Override + public void setCharset(Charset charset) { + this.charset = charset; + } +} diff --git a/src/main/java/com/warxim/petep/core/pdu/PDU.java b/src/main/java/com/warxim/petep/core/pdu/PDU.java new file mode 100644 index 0000000..6e294ba --- /dev/null +++ b/src/main/java/com/warxim/petep/core/pdu/PDU.java @@ -0,0 +1,150 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.core.pdu; + +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.Set; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.interceptor.worker.Interceptor; +import com.warxim.petep.proxy.worker.Proxy; + +/** PDU (Protocol Data Unit) is core unit for data processed in PETEP. */ +@PetepAPI +public abstract class PDU { + /** Parent proxy. */ + protected Proxy proxy; + + /** Parent connection. */ + protected Connection connection; + + /** PDU destination. */ + protected PduDestination destination; + + /** Interceptor in which was the PDU processed last time. */ + protected Interceptor lastInterceptor; + + /** PDU tags. */ + protected Set tags; + + /** PDU constructor */ + public PDU(Proxy proxy, Connection connection, PduDestination destination, Set tags) { + this.proxy = proxy; + this.destination = destination; + this.connection = connection; + this.tags = tags; + } + + /* + * TAGS + */ + /** Does the PDU contain specified tag? */ + public boolean hasTag(String tag) { + return tags.contains(tag); + } + + /** Adds tag to the PDU. */ + public void addTag(String tag) { + tags.add(tag); + } + + /** Removes tag from the PDU. */ + public void removeTag(String tag) { + tags.remove(tag); + } + + /** Removes tag from the PDU. */ + public void addTags(Collection tags) { + this.tags.addAll(tags); + } + + /* + * GETTERS + */ + /** Returns set of tags. */ + public Set getTags() { + return tags; + } + + /** Returns parent proxy. */ + public Proxy getProxy() { + return proxy; + } + + /** Returns PDU destination. */ + public PduDestination getDestination() { + return destination; + } + + /** Returns connection. */ + public Connection getConnection() { + return connection; + } + + /** Returns interceptor. */ + public Interceptor getLastInterceptor() { + return lastInterceptor; + } + + /* + * SETTERS + */ + /** Sets parent proxy. */ + public void setProxy(Proxy proxy) { + this.proxy = proxy; + } + + /** Sets PDU destination. */ + public void setDestination(PduDestination destination) { + this.destination = destination; + } + + /** Sets connection. */ + public void setConnection(Connection connection) { + this.connection = connection; + } + + /** Sets interceptor. */ + public void setLastInterceptor(Interceptor interceptor) { + this.lastInterceptor = interceptor; + } + + /* + * ABSTRACT METHODS + */ + /** Returns buffer. */ + public abstract byte[] getBuffer(); + + /** Returns size of data in the buffer. */ + public abstract int getSize(); + + /** Returns the buffer and size of data in the buffer. */ + public abstract void setBuffer(byte[] buffer, int size); + + /** Resizes the buffer. */ + public abstract void resize(int size); + + /** Returns the charset of the PDU. */ + public abstract Charset getCharset(); + + /** Sets the charset of the PDU. */ + public abstract void setCharset(Charset charset); + + /** Creates deep copy of the PDU. */ + public abstract PDU copy(); +} diff --git a/src/main/java/com/warxim/petep/core/pdu/PduDestination.java b/src/main/java/com/warxim/petep/core/pdu/PduDestination.java new file mode 100644 index 0000000..77c693a --- /dev/null +++ b/src/main/java/com/warxim/petep/core/pdu/PduDestination.java @@ -0,0 +1,25 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.core.pdu; + +import com.warxim.petep.extension.PetepAPI; + +/** Destination of PDU. */ +@PetepAPI +public enum PduDestination { + CLIENT, SERVER +} diff --git a/src/main/java/com/warxim/petep/core/pdu/PduQueue.java b/src/main/java/com/warxim/petep/core/pdu/PduQueue.java new file mode 100644 index 0000000..9cac97f --- /dev/null +++ b/src/main/java/com/warxim/petep/core/pdu/PduQueue.java @@ -0,0 +1,61 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.core.pdu; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import com.warxim.petep.extension.PetepAPI; + +/* Queue of PDUs. */ +@PetepAPI +public class PduQueue { + private final BlockingQueue queue; + + public PduQueue() { + queue = new LinkedBlockingQueue<>(); + } + + /** Add PDU to queue. */ + public void add(PDU pdu) { + queue.add(pdu); + } + + /** Returns PDU from queue (blocks until there is PDU). */ + public PDU take() throws InterruptedException { + return queue.take(); + } + + /** Returns queue size. */ + public int size() { + return queue.size(); + } + + /** Clears queue. */ + public void clear() { + queue.clear(); + } + + /** Returns true if the queue is empty. */ + public boolean isEmpty() { + return queue.isEmpty(); + } + + /** Retrieves and removes the head of the queue. */ + public PDU poll() { + return queue.poll(); + } +} diff --git a/src/main/java/com/warxim/petep/exception/CommandLineArgumentsException.java b/src/main/java/com/warxim/petep/exception/CommandLineArgumentsException.java new file mode 100644 index 0000000..69c65b5 --- /dev/null +++ b/src/main/java/com/warxim/petep/exception/CommandLineArgumentsException.java @@ -0,0 +1,26 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.exception; + +/** Command line arguments exception for invalid arguments. */ +public final class CommandLineArgumentsException extends Exception { + private static final long serialVersionUID = 1L; + + public CommandLineArgumentsException(String message) { + super(message); + } +} diff --git a/src/main/java/com/warxim/petep/exception/ConfigurationException.java b/src/main/java/com/warxim/petep/exception/ConfigurationException.java new file mode 100644 index 0000000..acc04cc --- /dev/null +++ b/src/main/java/com/warxim/petep/exception/ConfigurationException.java @@ -0,0 +1,33 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.exception; + +/** + * Configuration exception for configuration errors (configuration does not exist, cannot be + * accessed, invalid fields, ...) + */ +public final class ConfigurationException extends Exception { + private static final long serialVersionUID = 1L; + + public ConfigurationException(String message) { + super(message); + } + + public ConfigurationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/warxim/petep/exception/ExtensionLoadException.java b/src/main/java/com/warxim/petep/exception/ExtensionLoadException.java new file mode 100644 index 0000000..f720a0a --- /dev/null +++ b/src/main/java/com/warxim/petep/exception/ExtensionLoadException.java @@ -0,0 +1,30 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.exception; + +/** Extension load exception. */ +public final class ExtensionLoadException extends Exception { + private static final long serialVersionUID = 1L; + + public ExtensionLoadException(String message) { + super(message); + } + + public ExtensionLoadException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/warxim/petep/extension/Extension.java b/src/main/java/com/warxim/petep/extension/Extension.java new file mode 100644 index 0000000..eed3d10 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/Extension.java @@ -0,0 +1,49 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension; + +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.helper.GuiHelper; + +/** Superclass for extensions. */ +@PetepAPI +public abstract class Extension { + /** Path where the extension .jar file is located. */ + protected final String path; + + public Extension(String path) { + this.path = path; + } + + public final String getPath() { + return path; + } + + /** Initializes the extension. */ + public abstract void init(ExtensionHelper helper); + + /** Initializes the extension GUI. */ + public abstract void initGui(GuiHelper helper); + + public abstract String getCode(); + + public abstract String getName(); + + public abstract String getDescription(); + + public abstract String getVersion(); +} diff --git a/src/main/java/com/warxim/petep/extension/ExtensionGuiInitListener.java b/src/main/java/com/warxim/petep/extension/ExtensionGuiInitListener.java new file mode 100644 index 0000000..d1d33c0 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/ExtensionGuiInitListener.java @@ -0,0 +1,28 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension; + +import com.warxim.petep.helper.GuiHelper; + +@PetepAPI +public interface ExtensionGuiInitListener { + /** Runs before extension GUIs are initialized. */ + void beforeInitGui(GuiHelper helper); + + /** Runs after extension GUIs are initialized. */ + void afterInitGui(GuiHelper helper); +} diff --git a/src/main/java/com/warxim/petep/extension/ExtensionInitListener.java b/src/main/java/com/warxim/petep/extension/ExtensionInitListener.java new file mode 100644 index 0000000..31a633c --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/ExtensionInitListener.java @@ -0,0 +1,28 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension; + +import com.warxim.petep.helper.ExtensionHelper; + +@PetepAPI +public interface ExtensionInitListener { + /** Runs before extensions are initialized. */ + void beforeInit(ExtensionHelper helper); + + /** Runs after extensions are initialized. */ + void afterInit(ExtensionHelper helper); +} diff --git a/src/main/java/com/warxim/petep/extension/ExtensionManager.java b/src/main/java/com/warxim/petep/extension/ExtensionManager.java new file mode 100644 index 0000000..686c7c9 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/ExtensionManager.java @@ -0,0 +1,100 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.helper.GuiHelper; + +/** Extension manager. */ +public final class ExtensionManager { + /** Map of extensions (key = extension code). */ + private final Map extensionMap; + + /** List of extensions. */ + private final List extensionList; + + /** + * Extension manager constructor that takes list of extensions and stores them to own unmodifiable + * collections. + */ + public ExtensionManager(List extensions) { + // Make list unmodifiable. + extensionList = Collections.unmodifiableList(extensions); + + // Fill map with extensions with code as key. + Map map = new HashMap<>((int) (extensions.size() / 0.75 + 1), 0.75f); + for (Extension extension : extensions) { + map.put(extension.getCode(), extension); + } + + // Make map unmodifiable + extensionMap = Collections.unmodifiableMap(map); + } + + /** Returns unmodifiable extensions map . */ + public Map getMap() { + return extensionMap; + } + + /** Returns unmodifiable extensions list. */ + public List getList() { + return extensionList; + } + + /** Returns extension by code. */ + public Extension getExtension(String code) { + return extensionMap.get(code); + } + + /** Inits extensions. */ + public void init(ExtensionHelper helper) { + // Call beforeInit on listeners. + extensionList.stream() + .filter(ExtensionInitListener.class::isInstance) + .map(ExtensionInitListener.class::cast) + .forEach(extension -> extension.beforeInit(helper)); + + extensionList.parallelStream().forEach(extension -> extension.init(helper)); + + // Call afterInit on listeners. + extensionList.stream() + .filter(ExtensionInitListener.class::isInstance) + .map(ExtensionInitListener.class::cast) + .forEach(extension -> extension.afterInit(helper)); + } + + /** Inits extensions GUI. */ + public void initGui(GuiHelper helper) { + // Call beforeInitGui on listeners. + extensionList.stream() + .filter(ExtensionGuiInitListener.class::isInstance) + .map(ExtensionGuiInitListener.class::cast) + .forEach(extension -> extension.beforeInitGui(helper)); + + extensionList.parallelStream().forEach(extension -> extension.initGui(helper)); + + // Call afterInitGui on listeners. + extensionList.stream() + .filter(ExtensionGuiInitListener.class::isInstance) + .map(ExtensionGuiInitListener.class::cast) + .forEach(extension -> extension.afterInitGui(helper)); + } +} diff --git a/src/main/java/com/warxim/petep/extension/PetepAPI.java b/src/main/java/com/warxim/petep/extension/PetepAPI.java new file mode 100644 index 0000000..b6ff78e --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/PetepAPI.java @@ -0,0 +1,31 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension; + +import static java.lang.annotation.RetentionPolicy.SOURCE; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Annotation signaling that the annotated element is part of extension API and should be used to + * generate PetepLib.jar for extensions. + */ +@Retention(SOURCE) +@Target(ElementType.TYPE) +public @interface PetepAPI { +} diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherController.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherController.java new file mode 100644 index 0000000..4ac7e83 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherController.java @@ -0,0 +1,212 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.catcher; + +import java.net.URL; +import java.util.ResourceBundle; +import java.util.Timer; +import java.util.TimerTask; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduQueue; +import com.warxim.petep.gui.control.PduEditor; +import com.warxim.petep.helper.PetepHelper; +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.control.Label; + +/** Catcher controller. */ +public final class CatcherController implements Initializable { + private static final int QUEUE_CHECK_PERIOD_MS = 500; + + private final PetepHelper petepHelper; + + /** Current PDU. */ + private PDU pdu; + + /** PDU queue. */ + private final PduQueue queue; + + /** Timer for checking queue for new PDUs. */ + private Timer timer; + + /** State of catcher (on, transition, off). */ + private CatcherState state; + + /* + * GUI + */ + @FXML + private PduEditor pduEditor; + @FXML + private Label stateLabel; + @FXML + private Button forwardButton; + @FXML + private Button dropButton; + @FXML + private Button startStopButton; + + /** Catcher controller constructor. */ + public CatcherController(PetepHelper petepHelper) { + this.petepHelper = petepHelper; + this.queue = new PduQueue(); + + // Stopped by default. + state = CatcherState.OFF; + } + + @Override + public void initialize(URL location, ResourceBundle resources) { + pduEditor.init(petepHelper); + + setDisableEditor(true); + } + + public void stop() { + if (timer != null) { + timer.cancel(); + } + } + + private void setDisableEditor(boolean value) { + forwardButton.setDisable(value); + dropButton.setDisable(value); + pduEditor.setDisable(value); + } + + private void checkQueue() { + Platform.runLater(() -> { + if (pdu == null) { + pdu = queue.poll(); + + // No PDU in queue. + if (pdu == null) { + return; + } + + // PDU has no_catch tag and does not have catch tag. (Let it be processed + // automatically in PETEP.) + if (pdu.hasTag("no_catch") && !pdu.hasTag("catch")) { + petepHelper.processPdu(pdu); + pdu = null; + checkQueue(); + return; + } + + // Set PDU to editor. + pduEditor.setPdu(pdu); + + // Enable editor. + setDisableEditor(false); + } + }); + } + + private void disable() { + Platform.runLater(() -> { + setDisableEditor(true); + + pdu = null; + }); + } + + @FXML + private void onInterceptStartStopButtonClick(ActionEvent event) { + if (state == CatcherState.ON) { + // Stop catcher. + // Update GUI. + state = CatcherState.TRANSITION; + stateLabel.setText("..."); + + // Process current PDU in PETEP. + if (pdu != null) { + petepHelper.processPdu(pdu); + } + + // Reset GUI. + disable(); + + // Clear + pduEditor.clear(); + + // Process PDUs from queue in PETEP. + while ((pdu = queue.poll()) != null) { + petepHelper.processPdu(pdu); + } + + // Cancel timer. + if (timer != null) { + timer.cancel(); + timer = null; + } + + // Update GUI. + stateLabel.setText("OFF"); + startStopButton.setText("START"); + + state = CatcherState.OFF; + } else { + // Start catcher. + // Create timer and schedule queue checking. + timer = new Timer(); + + timer.schedule(new TimerTask() { + @Override + public void run() { + checkQueue(); + } + }, 0, QUEUE_CHECK_PERIOD_MS); + + // Update GUI. + stateLabel.setText("ON"); + startStopButton.setText("STOP"); + + // Set state to ON. + state = CatcherState.ON; + } + } + + @FXML + private void onDropButtonClick(ActionEvent event) { + disable(); + } + + @FXML + private void onForwardButtonClick(ActionEvent event) { + // Process PDU in PETEP. + petepHelper.processPdu(pduEditor.getPdu()); + + // Reset GUI. + disable(); + + // Check for new PDU. + checkQueue(); + } + + /** Adds PDU to catcher queue. */ + public void catchPdu(PDU data) { + queue.add(data); + } + + /** Returns catcher state. */ + public CatcherState getState() { + return state; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherExtension.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherExtension.java new file mode 100644 index 0000000..0636a81 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherExtension.java @@ -0,0 +1,112 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.catcher; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.common.ContextType; +import com.warxim.petep.core.listener.PetepListener; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.helper.GuiHelper; +import com.warxim.petep.helper.PetepHelper; +import javafx.fxml.FXMLLoader; +import javafx.scene.Node; + +/** Catcher extension. */ +public final class CatcherExtension extends Extension { + private GuiHelper guiHelper; + private Node node; + private CatcherController controller; + + /** Catcher extension constructor. */ + public CatcherExtension(String path) { + super(path); + } + + @Override + public void init(ExtensionHelper helper) { + // Register PETEP listener if GUI is enabled. + if (helper.getContextType() == ContextType.GUI) { + helper.registerPetepListener(new PetepListener() { + @Override + public void beforePrepare(PetepHelper helper) { + // Load catcher tab. + try { + FXMLLoader fxmlLoader = new FXMLLoader( + getClass().getResource("/fxml/extension/internal/catcher/Catcher.fxml")); + + controller = new CatcherController(helper); + + fxmlLoader.setController(controller); + + node = fxmlLoader.load(); + + guiHelper.registerTab("Catcher", node); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not load catcher GUI!", e); + } + } + + @Override + public void beforeStop(PetepHelper helper) { + // Unload catcher tab. + guiHelper.unregisterTab(node); + + // Clear memory. + node = null; + controller.stop(); + controller = null; + } + }); + } + + helper.registerInterceptorModuleFactory(new CatcherInterceptorModuleFactory(this)); + } + + @Override + public void initGui(GuiHelper helper) { + guiHelper = helper; + + helper.registerGuide(new CatcherGuide()); + } + + @Override + public String getCode() { + return "catcher"; + } + + @Override + public String getName() { + return "Catcher"; + } + + @Override + public String getDescription() { + return "Catches PDUs and allows user to edit them before relasing (manual intercepting)."; + } + + @Override + public String getVersion() { + return "1.0"; + } + + public CatcherController getController() { + return controller; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherGuide.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherGuide.java new file mode 100644 index 0000000..0e22224 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherGuide.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.catcher; + +import com.warxim.petep.gui.guide.Guide; + +/** Catcher guide. */ +public final class CatcherGuide extends Guide { + @Override + public String getTitle() { + return "Catcher"; + } + + @Override + public String getHtml() { + return loadHtmlResource("/html/guide/internal/CatcherGuide.html"); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptor.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptor.java new file mode 100644 index 0000000..cd67552 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptor.java @@ -0,0 +1,83 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.catcher; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.interceptor.worker.Interceptor; + +/** Catcher interceptor. */ +public final class CatcherInterceptor extends Interceptor { + private static final int RECHECK_STATE_PERIOD_MS = 25; + private CatcherController controller; + + /** Catcher interceptor constructor. */ + public CatcherInterceptor(int id, InterceptorModule module, PetepHelper helper) { + super(id, module, helper); + } + + @Override + public boolean prepare() { + // Get controller. + controller = ((CatcherExtension) module.getFactory().getExtension()).getController(); + return true; + } + + @Override + public boolean intercept(PDU pdu) { + if (controller == null) { + // Controller does not exist, let PDU go through. + return true; + } else { + // PDU has no_catch_skip tag and does not have catch tag. (Let it go through the interceptor.) + if (pdu.hasTag("no_catch_skip") && !pdu.hasTag("catch")) { + return true; + } + + // If controller is in transition, wait, so we do not mix PDU order. + while (controller.getState() == CatcherState.TRANSITION) { + try { + Thread.sleep(RECHECK_STATE_PERIOD_MS); + } catch (InterruptedException e) { + // Interrupted + Thread.currentThread().interrupt(); + return false; + } + } + + // If catcher is disabled, let PDU go through. + if (controller.getState() == CatcherState.OFF) { + return true; + } + + // Set this interceptor as last PDU interceptor. + pdu.setLastInterceptor(this); + + // Intercept PDU in GUI. + controller.catchPdu(pdu); + + // Do not let PDU go to the next interceptor. + return false; + } + } + + @Override + public void stop() { + // No action needed. + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptorModule.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptorModule.java new file mode 100644 index 0000000..06eb6dc --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptorModule.java @@ -0,0 +1,40 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.catcher; + +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.interceptor.worker.Interceptor; + +/** Catcher interceptor module. */ +public final class CatcherInterceptorModule extends InterceptorModule { + /** Catcher interceptor module constructor. */ + public CatcherInterceptorModule( + InterceptorModuleFactory factory, + String code, + String name, + String description, + boolean enabled) { + super(factory, code, name, description, enabled); + } + + @Override + public Interceptor createInterceptor(int id, PetepHelper helper) { + return new CatcherInterceptor(id, this, helper); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptorModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptorModuleFactory.java new file mode 100644 index 0000000..5f8ae2a --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherInterceptorModuleFactory.java @@ -0,0 +1,48 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.catcher; + +import com.warxim.petep.extension.Extension; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.module.InterceptorModule; + +/** Catcher interceptor module factory. */ +public final class CatcherInterceptorModuleFactory extends InterceptorModuleFactory { + /** Catcher interceptor module factory constructor. */ + public CatcherInterceptorModuleFactory(Extension extension) { + super(extension); + } + + @Override + public String getName() { + return "Catcher"; + } + + @Override + public String getCode() { + return "catcher"; + } + + @Override + public InterceptorModule createModule( + String code, + String name, + String description, + boolean enabled) { + return new CatcherInterceptorModule(this, code, name, description, enabled); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherState.java b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherState.java new file mode 100644 index 0000000..3b8a3ce --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/catcher/CatcherState.java @@ -0,0 +1,27 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.catcher; + +/** + * Catcher state.
+ * ON = catcher is enabled.
+ * OFF = catcher is disabled.
+ * TRANSITION = catcher is in transition state between ON and OFF. + */ +public enum CatcherState { + ON, OFF, TRANSITION +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/Rule.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/Rule.java new file mode 100644 index 0000000..0924e27 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/Rule.java @@ -0,0 +1,43 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group; + +/** Rule. */ +public class Rule { + protected final String name; + protected final String description; + protected final boolean enabled; + + /** Rule constructor. */ + public Rule(String name, String description, boolean enabled) { + this.name = name; + this.description = description; + this.enabled = enabled; + } + + public final String getName() { + return name; + } + + public final String getDescription() { + return description; + } + + public final boolean isEnabled() { + return enabled; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/RuleGroup.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/RuleGroup.java new file mode 100644 index 0000000..daac07c --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/RuleGroup.java @@ -0,0 +1,84 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** Group of rules. */ +public class RuleGroup { + private String code; + private String name; + + private final CopyOnWriteArrayList rules; + + /** Rule group constructor. */ + public RuleGroup(String code, String name) { + this.code = code; + this.name = name; + rules = new CopyOnWriteArrayList<>(); + } + + public final String getCode() { + return code; + } + + public final String getName() { + return name; + } + + public final void setCode(String code) { + this.code = code; + } + + public final void setName(String code) { + this.name = code; + } + + public final List getRules() { + return rules; + } + + public final int size() { + return rules.size(); + } + + public final boolean addRule(R rule) { + return rules.add(rule); + } + + public final void setRule(int index, R rule) { + rules.set(index, rule); + } + + public final void replace(R oldRule, R newRule) { + rules.set(rules.indexOf(oldRule), newRule); + } + + public final boolean removeRule(R rule) { + return rules.remove(rule); + } + + public final void swapRules(int what, int with) { + Collections.swap(rules, what, with); + } + + public final int ruleCount() { + return rules.size(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/RuleGroupManager.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/RuleGroupManager.java new file mode 100644 index 0000000..407c77b --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/RuleGroupManager.java @@ -0,0 +1,80 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Logger; + +/** Manager of groups of rules. */ +public class RuleGroupManager> { + private final ConcurrentHashMap groups; + + /** Rule group manager constructor. */ + public RuleGroupManager() { + groups = new ConcurrentHashMap<>(); + } + + /** Rule group manager constructor. */ + public RuleGroupManager(List groups) { + this(); + for (G group : groups) { + if (!add(group)) { + Logger.getGlobal() + .severe("Rule group " + group.getCode() + + " was not loaded, because group with this code already exists!"); + } + } + } + + /** Returns true if manager contains specified code. */ + public final boolean contains(String code) { + return groups.containsKey(code); + } + + /** Returns group for specified code. */ + public final G get(String code) { + return groups.get(code); + } + + /** Returns true if group was successfully added. Returns false if group code is reserved. */ + public final boolean add(G group) { + return groups.putIfAbsent(group.getCode(), group) == null; + } + + /** Removes group by its code. */ + public final void remove(String code) { + groups.remove(code); + } + + /** Returns list of groups. */ + public final List getList() { + return new ArrayList<>(groups.values()); + } + + /** Returns map of groups. */ + public final Map getMap() { + return groups; + } + + /** Returns number of groups. */ + public final int size() { + return groups.size(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/config/RuleGroupsConfig.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/config/RuleGroupsConfig.java new file mode 100644 index 0000000..35c25e2 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/config/RuleGroupsConfig.java @@ -0,0 +1,35 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group.config; + +import java.util.List; +import com.warxim.petep.extension.internal.common.rule_group.Rule; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; + +/** Configuratioon of groups of roles. */ +public final class RuleGroupsConfig { + private final List> groups; + + /** Rule groups configuration constructor. */ + public RuleGroupsConfig(List> groups) { + this.groups = groups; + } + + public final List> getRuleGroups() { + return groups; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/config/RuleInterceptorConfig.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/config/RuleInterceptorConfig.java new file mode 100644 index 0000000..1f1277a --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/config/RuleInterceptorConfig.java @@ -0,0 +1,31 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group.config; + +/** Rule interceptor configuration. */ +public final class RuleInterceptorConfig { + private final String ruleGroupCode; + + /** Rule interceptor configuration constructor. */ + public RuleInterceptorConfig(String ruleGroupCode) { + this.ruleGroupCode = ruleGroupCode; + } + + public final String getRuleGroupCode() { + return ruleGroupCode; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/EditRuleGroupDialog.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/EditRuleGroupDialog.java new file mode 100644 index 0000000..f573110 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/EditRuleGroupDialog.java @@ -0,0 +1,66 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group.gui; + +import java.io.IOException; +import com.warxim.petep.extension.internal.common.rule_group.Rule; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager; +import com.warxim.petep.gui.dialog.Dialogs; + +/** Dialog for editing of existing rule group. */ +public final class EditRuleGroupDialog extends RuleGroupDialog { + private final RuleGroup group; + + /** Edit rule group dialog constructor. */ + public EditRuleGroupDialog(RuleGroupManager> manager, RuleGroup group) + throws IOException { + super(manager, "Edit rule group", "Save"); + this.group = group; + + codeInput.setText(group.getCode()); + nameInput.setText(group.getName()); + } + + @Override + protected boolean isValid() { + if (!super.isValid()) { + return false; + } + + if (!group.getCode().equals(codeInput.getText()) && manager.contains(codeInput.getText())) { + Dialogs.createErrorDialog("Code used", + "The specified code is already used by other rule group."); + return false; + } + + return true; + } + + @Override + protected RuleGroup obtainResult() { + if (group.getCode().equals(codeInput.getText()) + && group.getName().equals(nameInput.getText())) { + return null; + } + + group.setCode(codeInput.getText()); + group.setName(nameInput.getText()); + + return group; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/NewRuleGroupDialog.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/NewRuleGroupDialog.java new file mode 100644 index 0000000..2d5c8f6 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/NewRuleGroupDialog.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group.gui; + +import java.io.IOException; +import com.warxim.petep.extension.internal.common.rule_group.Rule; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager; +import com.warxim.petep.gui.dialog.Dialogs; + +/** Dialog for creating new rule group. */ +public final class NewRuleGroupDialog extends RuleGroupDialog { + /** New rule group dialog constructor. */ + public NewRuleGroupDialog(RuleGroupManager> manager) throws IOException { + super(manager, "New rule group", "Create"); + } + + @Override + protected boolean isValid() { + if (!super.isValid()) { + return false; + } + + if (manager.contains(codeInput.getText())) { + Dialogs.createErrorDialog("Code used", + "The specified code is already used by other rule group."); + return false; + } + + return true; + } + + @Override + protected RuleGroup obtainResult() { + return new RuleGroup<>(codeInput.getText(), nameInput.getText()); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupController.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupController.java new file mode 100644 index 0000000..a5cd924 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupController.java @@ -0,0 +1,34 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group.gui; + +import com.warxim.petep.extension.internal.common.rule_group.Rule; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; + +/** Rule group controller. */ +public abstract class RuleGroupController { + protected final RuleGroup group; + + /** Rule group controller constructor. */ + public RuleGroupController(RuleGroup group) { + this.group = group; + } + + public final RuleGroup getRuleGroup() { + return group; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupDialog.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupDialog.java new file mode 100644 index 0000000..a2e5bd6 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupDialog.java @@ -0,0 +1,58 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group.gui; + +import java.io.IOException; +import com.warxim.petep.extension.internal.common.rule_group.Rule; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.gui.dialog.SimpleInputDialog; +import javafx.fxml.FXML; +import javafx.scene.control.TextField; + +/** Rule group dialog. */ +public abstract class RuleGroupDialog extends SimpleInputDialog> { + @FXML + protected TextField nameInput; + @FXML + protected TextField codeInput; + + protected final RuleGroupManager> manager; + + /** Rule group dialog constructor. */ + public RuleGroupDialog(RuleGroupManager> manager, String title, String okText) + throws IOException { + super("/fxml/extension/internal/common/rule_group/RuleGroupDialog.fxml", title, okText); + this.manager = manager; + } + + @Override + protected boolean isValid() { + if (nameInput.getText().length() == 0) { + Dialogs.createErrorDialog("Name required", "You have to enter name."); + return false; + } + + if (codeInput.getText().length() == 0) { + Dialogs.createErrorDialog("Code required", "You have to enter code."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupsController.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupsController.java new file mode 100644 index 0000000..d702a05 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupsController.java @@ -0,0 +1,204 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group.gui; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.extension.internal.common.rule_group.Rule; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager; +import com.warxim.petep.extension.internal.common.rule_group.intercept.RuleInterceptorModule; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.util.GuiUtils; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.control.TabPane; +import javafx.util.Pair; + +/** Controller or rule groups (contains tabs of rule groups). */ +public abstract class RuleGroupsController implements Initializable { + private final ExtensionHelper helper; + private final RuleGroupManager> manager; + private final List> controllers; + + private final String title; + + @FXML + private TabPane tabs; + @FXML + private Label titleLabel; + + /** Rule groups controller constrcutor. */ + public RuleGroupsController( + String title, + RuleGroupManager> groupManager, + ExtensionHelper extensionHelper) { + this.title = title; + helper = extensionHelper; + manager = groupManager; + controllers = new ArrayList<>(); + } + + @Override + public void initialize(URL location, ResourceBundle resources) { + for (RuleGroup group : manager.getMap().values()) { + addGroupTab(group); + } + + titleLabel.setText(title); + } + + /** Adds new tab for rule group to the tab pane. */ + private final void addGroupTab(RuleGroup group) { + try { + Pair> pair = createGroupTabNode(group); + + controllers.add(pair.getValue()); + + GuiUtils.addTabToTabPane(tabs, group.getName(), pair.getKey()); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not load group tab!", e); + } + } + + @FXML + private final void onNewButtonClick(ActionEvent event) { + try { + NewRuleGroupDialog dialog = new NewRuleGroupDialog<>(manager); + + Optional> data = dialog.showAndWait(); + + if (!data.isPresent() || data.get() == null) { + return; + } + + manager.add(data.get()); + + addGroupTab(data.get()); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during openning of group dialog", e); + } + } + + @FXML + private final void onEditButtonClick(ActionEvent event) { + RuleGroup group = + controllers.get(tabs.getSelectionModel().getSelectedIndex()).getRuleGroup(); + + if (group == null) { + return; + } + + String oldCode = group.getCode(); + + try { + EditRuleGroupDialog dialog = new EditRuleGroupDialog<>(manager, group); + + Optional> data = dialog.showAndWait(); + + if (!data.isPresent() || data.get() == null) { + return; + } + + manager.remove(oldCode); + manager.add(data.get()); + + tabs.getSelectionModel().getSelectedItem().setText(data.get().getName()); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during openning of rule group dialog", e); + } + } + + @FXML + private final void onRemoveButtonClick(ActionEvent event) { + int index = tabs.getSelectionModel().getSelectedIndex(); + + RuleGroup group = controllers.get(index).getRuleGroup(); + + if (group == null) { + return; + } + + if (isGroupUsed(group)) { + Dialogs.createErrorDialog("Rule group is used", + "Rule group is used by interceptors and cannot be deleted. Please, remove interceptors that use this group first."); + return; + } + + // Does user really want to remove group? + if (!Dialogs.createYesOrNoDialog("Are you sure?", + "Do you really want to remove group '" + group.getName() + "'?")) { + return; + } + + // Remove group + manager.remove(group.getCode()); + + // Remove controller + controllers.remove(index); + + // Remove tab + tabs.getTabs().remove(index); + } + + /** Check whether the group is used by any interceptor modules. */ + private final boolean isGroupUsed(RuleGroup group) { + Class> moduleClass = getInterceptorModuleClass(); + + // Check modules in direction C2S (Client -> Server) + for (InterceptorModule module : helper.getInterceptorModulesC2S()) { + if (!(moduleClass.isInstance(module))) { + continue; + } + + if (moduleClass.cast(module).getRuleGroup() == group) { + return true; + } + } + + // Check modules in direction S2C (Client <- Server) + for (InterceptorModule module : helper.getInterceptorModulesS2C()) { + if (!(moduleClass.isInstance(module))) { + continue; + } + + if (moduleClass.cast(module).getRuleGroup() == group) { + return true; + } + } + + return false; + } + + /** Creates group tab node for rule group. */ + protected abstract Pair> createGroupTabNode(RuleGroup group) + throws IOException; + + /** Returns interceptor module class. */ + protected abstract Class> getInterceptorModuleClass(); +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupsGuiFactory.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupsGuiFactory.java new file mode 100644 index 0000000..b68df78 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleGroupsGuiFactory.java @@ -0,0 +1,34 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * This p am 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group.gui; + +import java.io.IOException; +import javafx.fxml.FXMLLoader; +import javafx.scene.Node; + +/** GUI factory that creates rule groups node (node for controlling groups of rules). */ +public class RuleGroupsGuiFactory { + private RuleGroupsGuiFactory() {} + + public static Node createRoleGroupsNode(RuleGroupsController controller) throws IOException { + FXMLLoader fxmlLoader = new FXMLLoader(RuleGroupsGuiFactory.class + .getResource("/fxml/extension/internal/common/rule_group/GroupsController.fxml")); + + fxmlLoader.setController(controller); + return fxmlLoader.load(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleInterceptorConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleInterceptorConfigurator.java new file mode 100644 index 0000000..819179b --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/gui/RuleInterceptorConfigurator.java @@ -0,0 +1,79 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group.gui; + +import java.io.IOException; +import com.warxim.petep.extension.internal.common.rule_group.Rule; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager; +import com.warxim.petep.extension.internal.common.rule_group.config.RuleInterceptorConfig; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.fxml.FXML; +import javafx.scene.control.ComboBox; +import javafx.util.StringConverter; + +/** Rule interceptor configurator. */ +public final class RuleInterceptorConfigurator + extends ConfigPane { + @FXML + private ComboBox> groupInput; + + private final RuleGroupManager> manager; + + /** Rule interceptor configurator constructor. */ + public RuleInterceptorConfigurator(RuleGroupManager> manager) throws IOException { + super("/fxml/extension/internal/common/rule_group/RuleInterceptorConfigurator.fxml"); + this.manager = manager; + + groupInput.getItems().setAll(manager.getList()); + + groupInput.setConverter(new StringConverter>() { + @Override + public String toString(RuleGroup group) { + return group == null ? "" : group.getName(); + } + + @Override + public RuleGroup fromString(String str) { + return null; + } + }); + + groupInput.getSelectionModel().selectLast(); + } + + @Override + public RuleInterceptorConfig getConfig() { + return new RuleInterceptorConfig(groupInput.getSelectionModel().getSelectedItem().getCode()); + } + + @Override + public void setConfig(RuleInterceptorConfig config) { + groupInput.getSelectionModel().select(manager.get(config.getRuleGroupCode())); + } + + @Override + public boolean isValid() { + if (groupInput.getSelectionModel().getSelectedItem() == null) { + Dialogs.createErrorDialog("Replace group required", "You have to select replace group."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/common/rule_group/intercept/RuleInterceptorModule.java b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/intercept/RuleInterceptorModule.java new file mode 100644 index 0000000..eacab57 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/common/rule_group/intercept/RuleInterceptorModule.java @@ -0,0 +1,38 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.common.rule_group.intercept; + +import com.warxim.petep.extension.internal.common.rule_group.Rule; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.module.InterceptorModule; + +/** Rule interceptor module. */ +public abstract class RuleInterceptorModule extends InterceptorModule { + /** Rule interceptor module constructor. */ + public RuleInterceptorModule( + InterceptorModuleFactory factory, + String code, + String name, + String description, + boolean enabled) { + super(factory, code, name, description, enabled); + } + + /** Returns rule group belonging to the interceptor. */ + public abstract RuleGroup getRuleGroup(); +} diff --git a/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewController.java b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewController.java new file mode 100644 index 0000000..97a8087 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewController.java @@ -0,0 +1,90 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.connection_view; + +import java.net.URL; +import java.util.ResourceBundle; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.proxy.worker.Proxy; +import javafx.beans.property.SimpleStringProperty; +import javafx.collections.FXCollections; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; + +/** Connection View controller. */ +public final class ConnectionViewController implements Initializable { + /** Target proxy. */ + private final Proxy proxy; + + @FXML + private TableView table; + @FXML + private TableColumn idColumn; + @FXML + private TableColumn infoColumn; + + /** Connection View controller constructor. */ + public ConnectionViewController(Proxy proxy) { + this.proxy = proxy; + } + + @Override + public void initialize(URL location, ResourceBundle resources) { + refresh(); + + createContextMenu(); + } + + private void createContextMenu() { + MenuItem killItem = new MenuItem("Kill"); + killItem.setOnAction(this::onKillConnectionClick); + + ContextMenu menu = new ContextMenu(); + menu.getItems().add(killItem); + table.setContextMenu(menu); + } + + private void onKillConnectionClick(ActionEvent event) { + Connection connection = table.getSelectionModel().getSelectedItem(); + + if (connection == null) { + return; + } + + connection.stop(); + refresh(); + } + + public void refresh() { + idColumn.setCellValueFactory(new PropertyValueFactory<>("id")); + infoColumn.setCellValueFactory(cell -> new SimpleStringProperty(cell.getValue().toString())); + + table.setItems(FXCollections.observableArrayList(proxy.getConnectionManager().getList())); + } + + public void killAll() { + proxy.getConnectionManager().getList().forEach(Connection::stop); + + refresh(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewExtension.java b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewExtension.java new file mode 100644 index 0000000..0991843 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewExtension.java @@ -0,0 +1,94 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.connection_view; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.common.ContextType; +import com.warxim.petep.core.listener.PetepListener; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.helper.GuiHelper; +import com.warxim.petep.helper.PetepHelper; +import javafx.application.Platform; +import javafx.fxml.FXMLLoader; + +/** Connection view extension. */ +public final class ConnectionViewExtension extends Extension { + private ConnectionViewsController controller; + + /** Connection view extension constructor. */ + public ConnectionViewExtension(String path) { + super(path); + } + + @Override + public void init(ExtensionHelper helper) { + if (helper.getContextType() != ContextType.GUI) { + return; + } + + helper.registerPetepListener(new PetepListener() { + @Override + public void afterPrepare(PetepHelper helper) { + Platform.runLater(() -> controller.load(helper)); + } + + @Override + public void beforeStop(PetepHelper helper) { + Platform.runLater(controller::unload); + } + }); + } + + @Override + public void initGui(GuiHelper helper) { + try { + FXMLLoader fxmlLoader = new FXMLLoader( + getClass().getResource("/fxml/extension/internal/connection_view/ConnectionViews.fxml")); + controller = new ConnectionViewsController(); + fxmlLoader.setController(controller); + + helper.registerTab("Connections", fxmlLoader.load()); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not load connection view!", e); + } + + helper.registerGuide(new ConnectionViewGuide()); + } + + @Override + public String getCode() { + return "connection_view"; + } + + @Override + public String getName() { + return "Connection View"; + } + + @Override + public String getDescription() { + return "Simple connection view."; + } + + @Override + public String getVersion() { + return "1.0"; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewGuide.java b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewGuide.java new file mode 100644 index 0000000..f69752a --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewGuide.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.connection_view; + +import com.warxim.petep.gui.guide.Guide; + +/** Connection view guide. */ +public final class ConnectionViewGuide extends Guide { + @Override + public String getTitle() { + return "Connection View"; + } + + @Override + public String getHtml() { + return loadHtmlResource("/html/guide/internal/ConnectionViewGuide.html"); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewsController.java b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewsController.java new file mode 100644 index 0000000..4a2b004 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/connection_view/ConnectionViewsController.java @@ -0,0 +1,120 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.connection_view; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.proxy.worker.Proxy; +import com.warxim.petep.util.GuiUtils; +import javafx.beans.value.ObservableValue; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; + +/** Connection views controller. */ +public final class ConnectionViewsController implements Initializable { + private final List controllers; + + @FXML + private TabPane tabs; + @FXML + private Button refreshButton; + + public ConnectionViewsController() { + controllers = new ArrayList<>(); + } + + @Override + public void initialize(URL location, ResourceBundle resources) { + refreshButton.setDisable(true); + tabs.setVisible(false); + + MenuItem killAllItem = new MenuItem("Kill All"); + killAllItem.setOnAction(this::onKillAllClick); + + ContextMenu menu = new ContextMenu(); + menu.getItems().add(killAllItem); + tabs.setContextMenu(menu); + } + + public void load(PetepHelper helper) { + // Create connection view tab for every proxy and its connection manager. + for (Proxy proxy : helper.getProxies()) { + try { + FXMLLoader fxmlLoader = new FXMLLoader( + getClass().getResource("/fxml/extension/internal/connection_view/ConnectionView.fxml")); + + ConnectionViewController controller = new ConnectionViewController(proxy); + controllers.add(controller); + fxmlLoader.setController(controller); + + GuiUtils.addTabToTabPane(tabs, proxy.getModule().getName(), fxmlLoader.load()); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not load connection view tab!", e); + } + } + + // Refresh connection view of proxy when its tab gets selected. + tabs.getSelectionModel().selectedItemProperty().addListener(this::onTabSelectionChange); + + refreshButton.setDisable(false); + tabs.setVisible(true); + } + + public void unload() { + refreshButton.setDisable(true); + tabs.setVisible(false); + controllers.clear(); + tabs.getTabs().clear(); + } + + private void onTabSelectionChange( + ObservableValue observable, + Tab oldTab, + Tab newTab) { + int index = tabs.getTabs().indexOf(newTab); + if (index != -1) { + controllers.get(index).refresh(); + } + } + + private void onKillAllClick(ActionEvent event) { + int index = tabs.getSelectionModel().getSelectedIndex(); + if (index != -1) { + controllers.get(index).killAll(); + } + } + + @FXML + private void onRefreshButtonClick(ActionEvent event) { + for (ConnectionViewController controller : controllers) { + controller.refresh(); + } + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPConfig.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPConfig.java new file mode 100644 index 0000000..48e3cdf --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPConfig.java @@ -0,0 +1,73 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy; + +/** External HTTP proxy configuration. */ +public final class EHTTPPConfig { + private String serverIp; + private int serverPort; + + private String proxyIp; + private int proxyPort; + + /** External HTTP configuration constructor. */ + public EHTTPPConfig(String serverIp, int serverPort, String proxyIp, int proxyPort) { + this.serverIp = serverIp; + this.serverPort = serverPort; + this.proxyIp = proxyIp; + this.proxyPort = proxyPort; + } + + public String getServerIp() { + return serverIp; + } + + public void setServerIp(String ip) { + serverIp = ip; + } + + public int getServerPort() { + return serverPort; + } + + public void setServerPort(int port) { + serverPort = port; + } + + public String getProxyIp() { + return proxyIp; + } + + public void setProxyIp(String ip) { + proxyIp = ip; + } + + public int getProxyPort() { + return proxyPort; + } + + public void setProxyPort(int port) { + proxyPort = port; + } + + public void set(String serverIp, int serverPort, String proxyIp, int proxyPort) { + this.serverIp = serverIp; + this.serverPort = serverPort; + this.proxyIp = proxyIp; + this.proxyPort = proxyPort; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPExtension.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPExtension.java new file mode 100644 index 0000000..12a272a --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPExtension.java @@ -0,0 +1,140 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy; + +import java.io.IOException; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.core.listener.PetepListener; +import com.warxim.petep.core.pdu.PduQueue; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.helper.GuiHelper; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.worker.Interceptor; +import com.warxim.petep.persistence.Storable; +import javafx.fxml.FXMLLoader; + +/** External HTTP proxy extension. */ +public final class EHTTPPExtension extends Extension implements Storable { + private EHTTPPManager manager; + private EHTTPPConfig config; + + /** External HTTP proxy extension constructor. */ + public EHTTPPExtension(String path) { + super(path); + manager = null; + Logger.getGlobal().info("HTTP Proxy extension loaded."); + } + + @Override + public void init(ExtensionHelper helper) { + Logger.getGlobal().info("HTTP Proxy extension registered."); + + if (config == null) { + // Use defaults. + config = new EHTTPPConfig("127.0.0.1", 8181, "127.0.0.1", 8080); + } + + helper.registerPetepListener(new PetepListener() { + /** Creates HTTP client for each HTTPP interceptor. */ + private void processInterceptors(List interceptors) { + for (Interceptor interceptor : interceptors) { + if (interceptor instanceof EHTTPPInterceptor) { + if (manager == null) { + manager = new EHTTPPManager(config); + } + + PduQueue queue = new PduQueue(); + + ((EHTTPPInterceptor) interceptor).setQueue(queue); + + // Create HTTPP client for interceptor queue and set the following interceptor as + // a target. + manager.createClient(queue, interceptor.getId() + 1); + } + } + } + + @Override + public void beforePrepare(PetepHelper helper) { + processInterceptors(helper.getInterceptorsC2S()); + processInterceptors(helper.getInterceptorsS2C()); + + if (manager != null) { + manager.start(helper); + } + } + + @Override + public void beforeStop(PetepHelper helper) { + if (manager != null) { + manager.stop(); + manager = null; + } + } + }); + + helper.registerInterceptorModuleFactory(new EHTTPPInterceptorModuleFactory(this)); + } + + @Override + public void initGui(GuiHelper helper) { + try { + FXMLLoader fxmlLoader = new FXMLLoader( + getClass().getResource("/fxml/extension/internal/ehttp/HTTPPSettings.fxml")); + fxmlLoader.setController(new EHTTPPSettingsController(config)); + helper.registerSettingsTab("HTTP Proxy", fxmlLoader.load()); + Logger.getGlobal().info("HTTP Proxy extension GUI registered."); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "HTTP Proxy tab could not be created.", e); + } + + helper.registerGuide(new EHTTPPGuide()); + } + + @Override + public String getCode() { + return "external_http_proxy"; + } + + @Override + public String getName() { + return "External HTTP Proxy"; + } + + @Override + public String getDescription() { + return "Internal extension for external HTTP proxy usage."; + } + + @Override + public String getVersion() { + return "1.0"; + } + + @Override + public EHTTPPConfig saveStore() { + return config; + } + + @Override + public void loadStore(EHTTPPConfig store) { + this.config = store; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPGuide.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPGuide.java new file mode 100644 index 0000000..cf670cc --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPGuide.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy; + +import com.warxim.petep.gui.guide.Guide; + +/** External HTTP Proxy guide. */ +public final class EHTTPPGuide extends Guide { + @Override + public String getTitle() { + return "External HTTP Proxy"; + } + + @Override + public String getHtml() { + return loadHtmlResource("/html/guide/internal/EHTTPPGuide.html"); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptor.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptor.java new file mode 100644 index 0000000..f8bee42 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptor.java @@ -0,0 +1,56 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduQueue; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.worker.Interceptor; + +/** External HTTP Proxy interceptor. */ +public final class EHTTPPInterceptor extends Interceptor { + private PduQueue queue; + + /** External HTTP Proxy interceptor constructor. */ + public EHTTPPInterceptor(int id, EHTTPPInterceptorModule module, PetepHelper helper) { + super(id, module, helper); + queue = null; + } + + @Override + public boolean prepare() { + return true; + } + + @Override + public boolean intercept(PDU pdu) { + if (queue != null && (pdu.hasTag("httpp") || !pdu.hasTag("no_httpp"))) { + queue.add(pdu); + return false; + } + return true; + } + + @Override + public void stop() { + // No action needed. + } + + public void setQueue(PduQueue queue) { + this.queue = queue; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptorModule.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptorModule.java new file mode 100644 index 0000000..95f6ffe --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptorModule.java @@ -0,0 +1,39 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy; + +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.interceptor.worker.Interceptor; + +/** External HTTP Proxy interceptor module. */ +public final class EHTTPPInterceptorModule extends InterceptorModule { + /** External HTTP Proxy interceptor module constructor. */ + public EHTTPPInterceptorModule( + EHTTPPInterceptorModuleFactory factory, + String code, + String name, + String description, + boolean enabled) { + super(factory, code, name, description, enabled); + } + + @Override + public Interceptor createInterceptor(int id, PetepHelper helper) { + return new EHTTPPInterceptor(id, this, helper); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptorModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptorModuleFactory.java new file mode 100644 index 0000000..7358b14 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPInterceptorModuleFactory.java @@ -0,0 +1,48 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy; + +import com.warxim.petep.extension.Extension; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.module.InterceptorModule; + +/** External HTTP Proxy interceptor module factory. */ +public final class EHTTPPInterceptorModuleFactory extends InterceptorModuleFactory { + /** External HTTP Proxy interceptor module factory constructor. */ + public EHTTPPInterceptorModuleFactory(Extension extension) { + super(extension); + } + + @Override + public String getName() { + return "External HTTP Proxy"; + } + + @Override + public String getCode() { + return "external_http_proxy"; + } + + @Override + public InterceptorModule createModule( + String code, + String name, + String description, + boolean enabled) { + return new EHTTPPInterceptorModule(this, code, name, description, enabled); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPManager.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPManager.java new file mode 100644 index 0000000..f64ba88 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPManager.java @@ -0,0 +1,75 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.Logger; +import com.warxim.petep.core.pdu.PduQueue; +import com.warxim.petep.extension.internal.external_http_proxy.lighthttp.LightHttpClient; +import com.warxim.petep.extension.internal.external_http_proxy.lighthttp.LightHttpServer; +import com.warxim.petep.helper.PetepHelper; + +/** External HTTP Proxy manager. */ +public final class EHTTPPManager { + private final EHTTPPConfig config; + private final List clients; + private final ExecutorService executor; + + private LightHttpServer server; + + /** External HTTP Proxy manager constructor. */ + public EHTTPPManager(EHTTPPConfig config) { + this.config = config; + clients = new ArrayList<>(); + executor = Executors.newCachedThreadPool(); + } + + /** Starts HTTP server and clients. */ + public void start(PetepHelper helper) { + // Create and start server. + server = new LightHttpServer(helper, config); + executor.submit(server::run); + + // Start clients. + for (LightHttpClient client : clients) { + executor.submit(client::start); + } + + Logger.getGlobal().info("HTTPP client-server started!"); + } + + /** Creates a client for specified queue. */ + public void createClient(PduQueue queue, int targetId) { + clients.add(new LightHttpClient(config, queue, targetId)); + } + + /** Stops HTTP server and clients. */ + public void stop() { + Logger.getGlobal().info("HTTPP client-server stopping..."); + + server.stop(); + + clients.parallelStream().forEach(LightHttpClient::stop); + + executor.shutdownNow(); + + Logger.getGlobal().info("HTTPP client-server stopped!"); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPSettingsController.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPSettingsController.java new file mode 100644 index 0000000..67ce822 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/EHTTPPSettingsController.java @@ -0,0 +1,93 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy; + +import java.net.URL; +import java.util.ResourceBundle; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.TextField; + +/** External HTTP Proxy settings controller. */ +public final class EHTTPPSettingsController implements Initializable { + private final EHTTPPConfig config; + + @FXML + private TextField serverIp; + @FXML + private TextField serverPort; + @FXML + private TextField proxyIp; + @FXML + private TextField proxyPort; + + public EHTTPPSettingsController(EHTTPPConfig config) { + this.config = config; + } + + @Override + public void initialize(URL location, ResourceBundle resources) { + serverIp.setText(config.getServerIp()); + serverPort.setText(String.valueOf(config.getServerPort())); + proxyIp.setText(config.getProxyIp()); + proxyPort.setText(String.valueOf(config.getProxyPort())); + } + + @FXML + private void onSaveButtonClick(ActionEvent event) { + String sIp = serverIp.getText(); + if (sIp.length() == 0) { + Dialogs.createErrorDialog("Server IP required", "You have to enter server IP."); + return; + } + + int sPort; + try { + sPort = Integer.parseInt(serverPort.getText()); + if (sPort <= 0 || sPort > 65535) { + Dialogs.createErrorDialog("Invalid server port", + "Server port has to be number (1 - 65535)."); + } + } catch (NumberFormatException e) { + Dialogs.createErrorDialog("Invalid server port", "Server port has to be number."); + return; + } + + String pIp = proxyIp.getText(); + if (pIp.length() == 0) { + Dialogs.createErrorDialog("Proxy IP required", "You have to enter proxy IP."); + return; + } + + int pPort; + try { + pPort = Integer.parseInt(proxyPort.getText()); + if (pPort <= 0 || pPort > 65535) { + Dialogs.createErrorDialog("Invalid proxy port", "Proxy port has to be number (1 - 65535)."); + } + } catch (NumberFormatException e) { + Dialogs.createErrorDialog("Invalid proxy port", "Proxy port has to be number."); + return; + } + + config.set(sIp, sPort, pIp, pPort); + + Dialogs.createInfoDialog("HTTP Proxy saved", "HTTP Proxy has been saved!"); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpClient.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpClient.java new file mode 100644 index 0000000..d95d86e --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpClient.java @@ -0,0 +1,201 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy.lighthttp; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ConnectException; +import java.net.Socket; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.core.pdu.PduQueue; +import com.warxim.petep.extension.internal.external_http_proxy.EHTTPPConfig; + +/** + * Light HTTP client. + */ +public final class LightHttpClient { + private final byte[] firstLineStart; + + private final EHTTPPConfig config; + + private final PduQueue queue; + + private final int targetInterceptorId; + + private boolean running; + + /** Light HTTP client constructor. */ + public LightHttpClient(EHTTPPConfig config, PduQueue queue, int targetId) { + this.config = config; + this.queue = queue; + this.targetInterceptorId = targetId; + + // Create first line. + byte[] serverIpBytes = config.getServerIp().getBytes(); + byte[] serverPortBytes = String.valueOf(config.getServerPort()).getBytes(); + + ByteBuffer buffer = ByteBuffer.allocate(LightHttpConstant.FIRST_LINE_START.length + 2 + + serverIpBytes.length + serverPortBytes.length); + buffer.put(LightHttpConstant.FIRST_LINE_START); + buffer.put(serverIpBytes); + buffer.put(LightHttpConstant.COLON); + buffer.put(serverPortBytes); + buffer.put(LightHttpConstant.SLASH); + + firstLineStart = buffer.array(); + } + + public void start() { + try { + running = true; + + work(); + } catch (InterruptedException e) { + // Shutdown + Thread.currentThread().interrupt(); + } + } + + public void stop() { + running = false; + } + + private void work() throws InterruptedException { + PDU pdu; + + while (running && (pdu = queue.take()) != null) { + while (running && pdu != null) { + try (Socket socket = new Socket(config.getProxyIp(), config.getProxyPort()); + OutputStream out = socket.getOutputStream(); + InputStream in = socket.getInputStream()) { + writePduToOutput(pdu, out); + readFromInput(in); + + pdu = null; + } catch (UnknownHostException e) { + Logger.getGlobal().log(Level.SEVERE, "Unknown host exception in HTTP Proxy!", e); + } catch (ConnectException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not connect to HTTP proxy!", e); + } catch (SocketException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not connect to HTTP proxy!", e); + // Interrupted + return; + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "IO exception in HTTP Proxy!", e); + } + } + } + } + + private void readFromInput(InputStream in) throws IOException { + // Read response + while (LightHttpUtils.readByte(in) != LightHttpConstant.CR) { + // Read until \r + } + + LightHttpUtils.skipNBytes(3, in); // \n\r\n + } + + private void writePduToOutput(PDU pdu, OutputStream out) throws IOException { + // First line + writeFirstLineToOutput(pdu, out); + + // Tags + writeTagsToOutput(pdu.getTags(), out); + + // Metadata + writeMetadataToOutput( + pdu.getProxy().getModule().getFactory().getSerializer().serializePduMetadata(pdu), out); + + // Content length + out.write(LightHttpConstant.CONTENT_LENGTH); + out.write(String.valueOf(pdu.getSize()).getBytes()); + out.write(LightHttpConstant.HEADER_END); + + // Content type + out.write(LightHttpConstant.CONTENT_TYPE_CHARSET); + out.write(pdu.getCharset().name().getBytes()); + + // End headers + out.write(LightHttpConstant.HEADERS_END); + + // Data + out.write(pdu.getBuffer(), 0, pdu.getSize()); + } + + private void writeFirstLineToOutput(PDU pdu, OutputStream out) throws IOException { + // First line start + out.write(firstLineStart); + + // Proxy + out.write(pdu.getProxy().getModule().getCode().getBytes()); + out.write(LightHttpConstant.SLASH); + // Connection + out.write(String.valueOf(pdu.getConnection().getId()).getBytes()); + out.write(LightHttpConstant.SLASH); + // Target Interceptor Id + out.write(String.valueOf(targetInterceptorId).getBytes()); + out.write(LightHttpConstant.SLASH); + // Destination + if (pdu.getDestination() == PduDestination.CLIENT) { + out.write(LightHttpConstant.S2C); + } else { + out.write(LightHttpConstant.C2S); + } + + // End first line + out.write(LightHttpConstant.FIRST_LINE_END); + } + + private void writeTagsToOutput(Set tags, OutputStream out) throws IOException { + if (!tags.isEmpty()) { + out.write(LightHttpConstant.TAGS_HEADER_BYTES); + + int remaining = tags.size(); + for (String tag : tags) { + out.write(tag.getBytes()); + + if (--remaining != 0) { + out.write(LightHttpConstant.TAGS_SEPARATOR); + } + } + out.write(LightHttpConstant.HEADER_END); + } + } + + private void writeMetadataToOutput(Map serializedMetaData, OutputStream out) + throws IOException { + if (serializedMetaData != null) { + for (var item : serializedMetaData.entrySet()) { + out.write(LightHttpConstant.METADATA_HEADER_START_BYTES); + out.write(item.getKey().getBytes()); + out.write(LightHttpConstant.HEADER_COLON); + out.write(item.getValue().getBytes()); + out.write(LightHttpConstant.HEADER_END); + } + } + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpConstant.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpConstant.java new file mode 100644 index 0000000..46ef20c --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpConstant.java @@ -0,0 +1,67 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy.lighthttp; + +public final class LightHttpConstant { + /* + * BYTES + */ + public static final byte COLON = (byte) 0x3A; + public static final byte SLASH = (byte) 0x2F; + public static final byte C2S = (byte) 0x73; + public static final byte S2C = (byte) 0x63; + public static final byte CR = (byte) 0x0D; + public static final byte LF = (byte) 0x0A; + public static final byte TAGS_SEPARATOR = ','; + + /* + * STRINGS + */ + public static final String TAGS_HEADER = "T"; + public static final String CONTENT_TYPE_HEADER = "Content-Type"; + public static final String CONTENT_LENGTH_HEADER = "Content-Length"; + public static final String METADATA_HEADER_START = "M-"; + + /* + * BYTE ARRAYS + */ + public static final byte[] FIRST_LINE_START = "POST http://".getBytes(); + public static final byte[] FIRST_LINE_END = " HTTP/1.0\r\n".getBytes(); + public static final byte[] CONTENT_LENGTH = (CONTENT_LENGTH_HEADER + ": ").getBytes(); + public static final byte[] CONTENT_TYPE_CHARSET = + (CONTENT_TYPE_HEADER + ": text/plain; charset=").getBytes(); + public static final byte[] TAGS_HEADER_BYTES = (TAGS_HEADER + ": ").getBytes(); + public static final byte[] METADATA_HEADER_START_BYTES = METADATA_HEADER_START.getBytes(); + public static final byte[] HEADER_COLON = ": ".getBytes(); + public static final byte[] HEADER_END = "\r\n".getBytes(); + public static final byte[] HEADERS_END = "\r\n\r\n".getBytes(); + + /* + * RESPONSES + */ + public static final byte[] RESPONSE_OK = "HTTP/1.0 OK\r\n\r\n".getBytes(); + public static final byte[] RESPONSE_WRONG_PROXY = + "HTTP/1.0 404 Proxy not found\r\n\r\n".getBytes(); + public static final byte[] RESPONSE_WRONG_CONNECTION = + "HTTP/1.0 404 Connection not found\r\n\r\n".getBytes(); + public static final byte[] RESPONSE_WRONG_INTERCEPTOR = + "HTTP/1.0 404 Interceptor not found\r\n\r\n".getBytes(); + public static final byte[] RESPONSE_DESERIALIZATION_ERROR = + "HTTP/1.0 500 Deserialization Error\r\n\r\n".getBytes(); + + private LightHttpConstant() {} +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpServer.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpServer.java new file mode 100644 index 0000000..c5c2c93 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpServer.java @@ -0,0 +1,357 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy.lighthttp; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.internal.external_http_proxy.EHTTPPConfig; +import com.warxim.petep.extension.internal.external_http_proxy.lighthttp.exception.InvalidDataException; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.proxy.worker.Proxy; + +/** Light HTTP server. */ +public final class LightHttpServer { + + private final PetepHelper helper; + + private final EHTTPPConfig config; + + private ServerSocket socket; + + private boolean running; + + private final int lastInterceptorC2SIndex; + private final int lastInterceptorS2CIndex; + + /** Light HTTP server constructor. */ + public LightHttpServer(PetepHelper helper, EHTTPPConfig config) { + this.helper = helper; + this.config = config; + this.lastInterceptorC2SIndex = helper.getInterceptorsC2S().size() + 1; + this.lastInterceptorS2CIndex = helper.getInterceptorsS2C().size() + 1; + } + + /** Runs server. */ + public void run() { + try { + socket = + new ServerSocket(config.getServerPort(), 0, InetAddress.getByName(config.getServerIp())); + + Logger.getGlobal() + .info("HTTP Server started on " + config.getServerIp() + ":" + config.getServerPort() + + "!"); + + running = true; + + while (running) { + accept(); + } + } catch (UnknownHostException e) { + Logger.getGlobal() + .log(Level.SEVERE, "Could not start HTTP server! (The host is unknown!)", e); + } catch (SocketException e) { + // Interrupted + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not start HTTP server!", e); + } finally { + try { + if (socket != null) { + socket.close(); + } + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not close HTTP server!", e); + } + } + Logger.getGlobal().log(Level.INFO, "HTTP server stopped."); + } + + /** Stops server. */ + public void stop() { + running = false; + + try { + if (socket != null) { + socket.close(); + } + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not close HTTP server!", e); + } + } + + /** Accepts new connections. */ + private void accept() { + try (Socket client = socket.accept(); + InputStream in = client.getInputStream(); + OutputStream out = client.getOutputStream()) { + try { + process(in, out); + } catch (InvalidDataException e) { + out.write(e.getMessageBytes()); + } + } catch (SocketException e) { + // Interrupted + } catch (Exception e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during HTTP read / write!", e); + } + } + + private Proxy readProxy(InputStream in, StringBuilder builder) + throws IOException, InvalidDataException { + int currentByte; + // Read proxy code + while ((currentByte = LightHttpUtils.readByte(in)) != 0x2F) { + builder.append((char) currentByte); + } + + Proxy proxy = helper.getProxy(builder.toString()); + if (proxy == null) { + throw new InvalidDataException(LightHttpConstant.RESPONSE_WRONG_PROXY); + } + + return proxy; + } + + private Connection readConnection(InputStream in, StringBuilder builder, Proxy proxy) + throws IOException, InvalidDataException { + int currentByte; + // Read client ID + while ((currentByte = LightHttpUtils.readByte(in)) != 0x2F) { + builder.append((char) currentByte); + } + + Connection connection = proxy.getConnectionManager().get(Integer.parseInt(builder.toString())); + + if (connection == null) { + throw new InvalidDataException(LightHttpConstant.RESPONSE_WRONG_CONNECTION); + } + + return connection; + } + + private PduDestination readDestination(InputStream in) throws IOException { + PduDestination destination; + + if (LightHttpUtils.readByte(in) == LightHttpConstant.S2C) { + destination = PduDestination.CLIENT; + } else { + destination = PduDestination.SERVER; + } + + return destination; + } + + private int readTargetInterceptor(InputStream in, StringBuilder builder) throws IOException { + int currentByte; + // Read target interceptor id + while ((currentByte = LightHttpUtils.readByte(in)) != 0x2F) { + // End of stream reached. + builder.append((char) currentByte); + } + return Integer.parseInt(builder.toString()); + } + + private void validateTargetInterceptor(PduDestination destination, int targetInterceptorId) + throws InvalidDataException { + if (targetInterceptorId < 0 + || (destination == PduDestination.SERVER && targetInterceptorId >= lastInterceptorC2SIndex) + || (destination == PduDestination.CLIENT + && targetInterceptorId >= lastInterceptorS2CIndex)) { + throw new InvalidDataException(LightHttpConstant.RESPONSE_WRONG_INTERCEPTOR); + } + } + + + /** + * Reads data from client input stream. TODO: change skip to skipNBytes in Java 12. + * + * @throws InvalidDataException + */ + private void process(InputStream in, OutputStream out) throws IOException, InvalidDataException { + // Skip POST / + LightHttpUtils.skipNBytes(6, in); + + StringBuilder builder = new StringBuilder(); + + // Proxy + Proxy proxy = readProxy(in, builder); + + builder.setLength(0); + + // Connection + Connection connection = readConnection(in, builder, proxy); + + builder.setLength(0); + + int targetInterceptorId = readTargetInterceptor(in, builder); + + // Read destination + PduDestination destination = readDestination(in); + + // Check validity of interceptor id. + validateTargetInterceptor(destination, targetInterceptorId); + + // Skip HTTP/1.0\r\n + LightHttpUtils.skipNBytes(11, in); + + // Read headers + Map serializedMetaData = new HashMap<>(); + Set tags = new HashSet<>(); + Charset charset = null; + int contentLength = 0; + + int currentByte; + + while (true) { + // Read first character to detect end of headers + currentByte = LightHttpUtils.readByte(in); + + if (currentByte == LightHttpConstant.CR) { + // skip \n\r\n + LightHttpUtils.skipNBytes(1, in); + break; + } + + // Read key + builder.setLength(0); + builder.append((char) currentByte); + while ((currentByte = LightHttpUtils.readByte(in)) != LightHttpConstant.COLON) { + builder.append((char) currentByte); + } + + String temp = builder.toString(); + + + // Skip space after : + LightHttpUtils.skipNBytes(1, in); + + builder.setLength(0); + + if (LightHttpConstant.CONTENT_LENGTH_HEADER.equals(temp)) { + contentLength = readContentLength(in, builder); + } else if (LightHttpConstant.CONTENT_TYPE_HEADER.equals(temp)) { + charset = readCharset(in, builder); + } else if (LightHttpConstant.TAGS_HEADER.equals(temp)) { + readTags(in, builder, tags); + } else if (temp.startsWith(LightHttpConstant.METADATA_HEADER_START)) { + serializedMetaData.put(temp.substring(2), readMetadata(in, builder)); + } else { + skipHeader(in); + } + + // Skip \n + LightHttpUtils.skipNBytes(1, in); + } + + // Read data. + byte[] buffer = in.readNBytes(contentLength); + + // Create PDU. + PDU pdu = proxy.getModule() + .getFactory() + .getDeserializer() + .deserializePdu(proxy, connection, destination, buffer, contentLength, tags, + serializedMetaData); + + if (pdu == null) { + out.write(LightHttpConstant.RESPONSE_DESERIALIZATION_ERROR); + return; + } + + // Set charset + if (charset != null) { + pdu.setCharset(charset); + } + + // Process PDU in PETEP. + helper.processPdu(pdu, targetInterceptorId); + + out.write(LightHttpConstant.RESPONSE_OK); + } + + private void skipHeader(InputStream in) throws IOException { + // Unknown header, skip value. + while (LightHttpUtils.readByte(in) != LightHttpConstant.CR) { + // Read until \r + } + } + + private int readContentLength(InputStream in, StringBuilder builder) throws IOException { + int currentByte; + // Read until \r + while ((currentByte = LightHttpUtils.readByte(in)) != LightHttpConstant.CR) { + builder.append((char) currentByte); + } + + return Integer.parseInt(builder.toString()); + } + + private String readMetadata(InputStream in, StringBuilder builder) throws IOException { + int currentByte; + // Read until \r + while ((currentByte = LightHttpUtils.readByte(in)) != LightHttpConstant.CR) { + builder.append((char) currentByte); + } + + return builder.toString(); + } + + private void readTags(InputStream in, StringBuilder builder, Set tags) + throws IOException { + int currentByte; + // Read until \r + while ((currentByte = LightHttpUtils.readByte(in)) != LightHttpConstant.CR) { + if (currentByte == LightHttpConstant.TAGS_SEPARATOR) { + tags.add(builder.toString()); + builder.setLength(0); + } else { + builder.append((char) currentByte); + } + } + + tags.add(builder.toString()); + } + + private Charset readCharset(InputStream in, StringBuilder builder) throws IOException { + // Skip text/plain; charset= + LightHttpUtils.skipNBytes(20, in); + + int currentByte; + + // Read until 0x0D = \r + while ((currentByte = LightHttpUtils.readByte(in)) != LightHttpConstant.CR) { + builder.append((char) currentByte); + } + + return Charset.forName(builder.toString()); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpUtils.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpUtils.java new file mode 100644 index 0000000..42527a5 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/LightHttpUtils.java @@ -0,0 +1,40 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy.lighthttp; + +import java.io.IOException; +import java.io.InputStream; + +public final class LightHttpUtils { + private LightHttpUtils() {} + + public static int readByte(InputStream in) throws IOException { + int c = in.read(); + + if (c == -1) { + throw new IOException("End of stream reached!"); + } + + return c; + } + + public static void skipNBytes(int n, InputStream in) throws IOException { + if (in.skip(n) != n) { + throw new IOException("Could not skip n bytes!"); + } + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/exception/InvalidDataException.java b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/exception/InvalidDataException.java new file mode 100644 index 0000000..f50e28e --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/external_http_proxy/lighthttp/exception/InvalidDataException.java @@ -0,0 +1,30 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.external_http_proxy.lighthttp.exception; + +public class InvalidDataException extends Exception { + private static final long serialVersionUID = 1L; + private final byte[] message; + + public InvalidDataException(byte[] message) { + this.message = message; + } + + public byte[] getMessageBytes() { + return message; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/HttpExtension.java b/src/main/java/com/warxim/petep/extension/internal/http/HttpExtension.java new file mode 100644 index 0000000..2fcc57a --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/HttpExtension.java @@ -0,0 +1,108 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http; + +import java.util.logging.Logger; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.ExtensionInitListener; +import com.warxim.petep.extension.internal.http.modifier.remove_header.RemoveHeaderModifierFactory; +import com.warxim.petep.extension.internal.http.proxy.HttpProxyModuleFactory; +import com.warxim.petep.extension.internal.http.tagger.has_header.HasHeaderSubruleFactory; +import com.warxim.petep.extension.internal.http.tagger.is_http.IsHttpSubruleFactory; +import com.warxim.petep.extension.internal.http.tagger.is_websocket.IsWebSocketSubruleFactory; +import com.warxim.petep.extension.internal.modifier.ModifierApi; +import com.warxim.petep.extension.internal.tagger.TaggerApi; +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.helper.GuiHelper; + +public final class HttpExtension extends Extension implements ExtensionInitListener { + /** HTTP extension constructor. */ + public HttpExtension(String path) { + super(path); + + Logger.getGlobal().info("HTTP extension loaded."); + } + + /** Initializes HTTP extension (registers HTTP proxy module). */ + @Override + public void init(ExtensionHelper helper) { + helper.registerProxyModuleFactory(new HttpProxyModuleFactory(this)); + + Logger.getGlobal().info("HTTP extension registered."); + } + + @Override + public void initGui(GuiHelper helper) { + // No action needed. + } + + @Override + public String getCode() { + return "http"; + } + + @Override + public String getName() { + return "HTTP extension"; + } + + @Override + public String getDescription() { + return "HTTP extension adds HTTP proxy to PETEP."; + } + + @Override + public String getVersion() { + return "1.0"; + } + + @Override + public void beforeInit(ExtensionHelper helper) { + // Get TagSubruleModule registrator. + Extension tagger = helper.getExtension("tagger"); + + // Register HasHeader subrule module. + if (tagger != null) { + TaggerApi registrator = ((TaggerApi) tagger); + if (!registrator.registerSubruleFactory(new HasHeaderSubruleFactory())) { + Logger.getGlobal().info("HTTP Extension could not register HasHeader tag subrule."); + } + + if (!registrator.registerSubruleFactory(new IsWebSocketSubruleFactory())) { + Logger.getGlobal().info("HTTP Extension could not register IsWebsocket tag subrule."); + } + + if (!registrator.registerSubruleFactory(new IsHttpSubruleFactory())) { + Logger.getGlobal().info("HTTP Extension could not register IsHTTP tag subrule."); + } + } + + // Get ModifierModule registrator. + Extension modifier = helper.getExtension("modifier"); + + // Register RemoveHeader module. + if (modifier != null && ((ModifierApi) modifier) + .registerModifierFactory(new RemoveHeaderModifierFactory())) { + Logger.getGlobal().info("HTTP Extension registered RemoveHeader modifier."); + } + } + + @Override + public void afterInit(ExtensionHelper helper) { + // No action needed. + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/gui/HttpMetadataPane.java b/src/main/java/com/warxim/petep/extension/internal/http/gui/HttpMetadataPane.java new file mode 100644 index 0000000..b99c270 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/gui/HttpMetadataPane.java @@ -0,0 +1,340 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.gui; + +import java.io.IOException; +import java.util.HashMap; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.internal.http.pdu.HttpPdu; +import com.warxim.petep.extension.internal.http.pdu.HttpRequestPdu; +import com.warxim.petep.extension.internal.http.pdu.HttpResponsePdu; +import com.warxim.petep.extension.internal.http.pdu.Opcode; +import com.warxim.petep.extension.internal.http.pdu.WebSocketPdu; +import com.warxim.petep.gui.component.PduMetadataPane; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.proxy.worker.Proxy; +import com.warxim.petep.util.BytesUtils; +import javafx.beans.binding.Bindings; +import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; +import javafx.collections.MapChangeListener; +import javafx.collections.ObservableList; +import javafx.collections.ObservableMap; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ComboBox; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.TextField; +import javafx.scene.layout.AnchorPane; +import javafx.util.Pair; + +public final class HttpMetadataPane extends PduMetadataPane { + /* + * HTTP + */ + @FXML + private AnchorPane httpPane; + + @FXML + private TextField httpVersionInput; + + @FXML + private TableView httpHeadersInput; + + @FXML + private TableColumn httpHeaderNameColumn; + @FXML + private TableColumn httpHeaderValueColumn; + + @FXML + private AnchorPane httpRequestPane; + + @FXML + private TextField httpMethodInput; + + @FXML + private TextField httpPathInput; + + @FXML + private AnchorPane httpResponsePane; + + @FXML + private TextField httpStatusCodeInput; + + @FXML + private TextField httpStatusMessageInput; + + private final ObservableMap httpHeaderMap; + + private final ObservableList httpHeaderNameList; + + /* + * WEBSOCKET + */ + @FXML + private AnchorPane websocketPane; + + @FXML + private CheckBox websocketFinInput; + + @FXML + private CheckBox websocketRsv1Input; + + @FXML + private CheckBox websocketRsv2Input; + + @FXML + private CheckBox websocketRsv3Input; + + @FXML + private CheckBox websocketMaskedInput; + + @FXML + private ComboBox websocketOpcodeInput; + + @FXML + private TextField websocketMaskInput; + + public HttpMetadataPane() throws IOException { + super("/fxml/extension/internal/http/HttpPduMetadata.fxml"); + + httpHeaderMap = FXCollections.observableHashMap(); + httpHeaderNameList = FXCollections.observableArrayList(); + + httpHeaderMap.addListener(this::onHeaderMapChange); + + httpHeaderNameColumn.setCellValueFactory(cd -> Bindings.createStringBinding(cd::getValue)); + httpHeaderValueColumn.setCellValueFactory(cd -> Bindings.valueAt(httpHeaderMap, cd.getValue())); + + httpHeadersInput.setItems(httpHeaderNameList); + + httpPane.managedProperty().bind(httpPane.visibleProperty()); + httpResponsePane.managedProperty().bind(httpResponsePane.visibleProperty()); + httpRequestPane.managedProperty().bind(httpRequestPane.visibleProperty()); + websocketPane.managedProperty().bind(websocketPane.visibleProperty()); + + // Disable mask input automatically. + websocketMaskedInput.selectedProperty().addListener(this::onWebsocketMaskedInputChange); + + // Setup opcodes. + websocketOpcodeInput.setItems(FXCollections.observableArrayList(Opcode.TEXT, Opcode.BINARY, + Opcode.CLOSE, Opcode.PING, Opcode.PONG, Opcode.CONTINUATION, Opcode.NON_CONTROL_1, + Opcode.NON_CONTROL_2, Opcode.NON_CONTROL_3, Opcode.NON_CONTROL_4, Opcode.NON_CONTROL_5, + Opcode.CONTROL_1, Opcode.CONTROL_2, Opcode.CONTROL_3, Opcode.CONTROL_4, Opcode.CONTROL_5)); + } + + private void onWebsocketMaskedInputChange( + ObservableValue observable, + boolean oldValue, + boolean newValue) { + websocketMaskInput.setDisable(oldValue); + } + + private void onHeaderMapChange( + MapChangeListener.Change change) { + boolean removed = change.wasRemoved(); + if (removed != change.wasAdded()) { + if (removed) { + httpHeaderNameList.remove(change.getKey()); + } else { + httpHeaderNameList.add(change.getKey()); + } + } + } + + @Override + public PDU getPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size) { + if (httpPane.isVisible()) { + return getHttpPdu(proxy, connection, destination, buffer, size); + } else { + return getWebSocketPdu(proxy, connection, destination, buffer, size); + } + } + + @Override + public void setPdu(PDU pdu) { + if (pdu instanceof HttpPdu) { + // HTTP + httpPane.setVisible(true); + websocketPane.setVisible(false); + + httpHeaderMap.putAll(((HttpPdu) pdu).getHeaders()); + + httpVersionInput.setText(((HttpPdu) pdu).getVersion()); + + if (pdu instanceof HttpRequestPdu) { + // HTTP Request + httpRequestPane.setVisible(true); + httpResponsePane.setVisible(false); + httpMethodInput.setText(((HttpRequestPdu) pdu).getMethod()); + httpPathInput.setText(((HttpRequestPdu) pdu).getPath()); + } else { + // HTTP Response + httpRequestPane.setVisible(false); + httpResponsePane.setVisible(true); + httpStatusCodeInput.setText(String.valueOf(((HttpResponsePdu) pdu).getStatusCode())); + httpStatusMessageInput.setText(((HttpResponsePdu) pdu).getStatusMessage()); + } + } else { + // WebSocket + httpPane.setVisible(false); + httpRequestPane.setVisible(false); + httpResponsePane.setVisible(false); + websocketPane.setVisible(true); + + websocketFinInput.setSelected(((WebSocketPdu) pdu).isFinal()); + websocketRsv1Input.setSelected(((WebSocketPdu) pdu).isRsv1()); + websocketRsv2Input.setSelected(((WebSocketPdu) pdu).isRsv2()); + websocketRsv3Input.setSelected(((WebSocketPdu) pdu).isRsv3()); + websocketMaskedInput.setSelected(((WebSocketPdu) pdu).isMasked()); + + websocketOpcodeInput.setValue(((WebSocketPdu) pdu).getOpcode()); + + if (((WebSocketPdu) pdu).isMasked()) { + websocketMaskInput.setText(BytesUtils.bytesToString(((WebSocketPdu) pdu).getMask())); + } else { + websocketMaskInput.setText(""); + } + } + } + + @Override + public void clear() { + httpHeadersInput.getItems().clear(); + httpVersionInput.clear(); + httpMethodInput.clear(); + httpPathInput.clear(); + httpStatusCodeInput.clear(); + httpStatusMessageInput.clear(); + websocketOpcodeInput.getSelectionModel().clearSelection(); + websocketFinInput.setSelected(false); + websocketRsv1Input.setSelected(false); + websocketRsv2Input.setSelected(false); + websocketRsv3Input.setSelected(false); + websocketMaskedInput.setSelected(false); + websocketMaskInput.clear(); + } + + private HttpPdu getHttpPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size) { + // HTTP + HttpPdu pdu; + if (httpRequestPane.isVisible()) { + // HTTP Request + pdu = new HttpRequestPdu(proxy, connection, destination, buffer, size); + + ((HttpRequestPdu) pdu).setPath(httpPathInput.getText()); + ((HttpRequestPdu) pdu).setMethod(httpMethodInput.getText()); + } else { + // HTTP Response + pdu = new HttpResponsePdu(proxy, connection, destination, buffer, size); + + ((HttpResponsePdu) pdu).setStatusCode(Integer.parseInt(httpStatusCodeInput.getText())); + ((HttpResponsePdu) pdu).setStatusMessage(httpStatusMessageInput.getText()); + } + + pdu.setVersion(httpVersionInput.getText()); + + pdu.addHeaders(new HashMap<>(httpHeaderMap)); + + return pdu; + } + + private WebSocketPdu getWebSocketPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size) { + // WebSocket + WebSocketPdu pdu = new WebSocketPdu(proxy, connection, destination, buffer, size); + + pdu.setFinal(websocketFinInput.isSelected()); + + pdu.setRsv1(websocketRsv1Input.isSelected()); + pdu.setRsv2(websocketRsv2Input.isSelected()); + pdu.setRsv3(websocketRsv3Input.isSelected()); + + pdu.setMasked(websocketMaskedInput.isSelected()); + + pdu.setOpcode(websocketOpcodeInput.getValue()); + + if (pdu.isMasked()) { + pdu.setMask(BytesUtils.stringToBytes(websocketMaskInput.getText())); + } + + return pdu; + } + + @FXML + private void onHttpHeaderAddButtonClick(ActionEvent event) { + Pair header = Dialogs.createTextPairDialog("Create header", "Name:", "Value:"); + + if (header == null) { + return; + } + + httpHeaderMap.put(header.getKey(), header.getValue()); + } + + @FXML + private void onHttpHeaderEditButtonClick(ActionEvent event) { + String item = httpHeadersInput.getSelectionModel().getSelectedItem(); + + if (item == null) { + return; + } + + Pair header = Dialogs.createTextPairDialog("Create header", "Name:", "Value:", + item, httpHeaderMap.get(item)); + + if (header == null) { + return; + } + + if (header.getKey().equals(item)) { + httpHeaderMap.replace(item, header.getValue()); + } else { + httpHeaderMap.remove(item); + httpHeaderMap.put(header.getKey(), header.getValue()); + } + } + + @FXML + private void onHttpHeaderRemoveButtonClick(ActionEvent event) { + String item = httpHeadersInput.getSelectionModel().getSelectedItem(); + + if (item == null) { + return; + } + + httpHeaderMap.remove(item); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderData.java b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderData.java new file mode 100644 index 0000000..b7a9168 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderData.java @@ -0,0 +1,31 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.modifier.remove_header; + +import com.warxim.petep.extension.internal.modifier.factory.ModifierData; + +public final class RemoveHeaderData extends ModifierData { + private final String header; + + public RemoveHeaderData(String header) { + this.header = header; + } + + public String getHeader() { + return header; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifier.java b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifier.java new file mode 100644 index 0000000..279792d --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifier.java @@ -0,0 +1,38 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.modifier.remove_header; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.http.pdu.HttpPdu; +import com.warxim.petep.extension.internal.modifier.factory.Modifier; +import com.warxim.petep.extension.internal.modifier.factory.ModifierData; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory; + +public final class RemoveHeaderModifier extends Modifier { + public RemoveHeaderModifier(ModifierFactory module, ModifierData data) { + super(module, data); + } + + @Override + public boolean process(PDU pdu) { + if (pdu instanceof HttpPdu) { + ((HttpPdu) pdu).removeHeader(((RemoveHeaderData) data).getHeader()); + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifierConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifierConfigurator.java new file mode 100644 index 0000000..a790603 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifierConfigurator.java @@ -0,0 +1,54 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * This program 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 distribut n 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 . + */ +package com.warxim.petep.extension.internal.http.modifier.remove_header; + +import java.io.IOException; +import com.warxim.petep.extension.internal.http.pdu.HttpUtils; +import com.warxim.petep.extension.internal.modifier.factory.ModifierConfigurator; +import com.warxim.petep.extension.internal.modifier.factory.ModifierData; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.fxml.FXML; +import javafx.scene.control.TextField; + +public final class RemoveHeaderModifierConfigurator extends ModifierConfigurator { + @FXML + private TextField nameInput; + + public RemoveHeaderModifierConfigurator() throws IOException { + super("/fxml/extension/internal/http/modifier/RemoveHeader.fxml"); + } + + @Override + public ModifierData getConfig() { + return new RemoveHeaderData(HttpUtils.formatHeaderName(nameInput.getText())); + } + + @Override + public void setConfig(ModifierData config) { + nameInput.setText(((RemoveHeaderData) config).getHeader()); + } + + @Override + public boolean isValid() { + if (nameInput.getText().length() == 0) { + Dialogs.createErrorDialog("Header required", "You have to enter header to remove."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifierFactory.java b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifierFactory.java new file mode 100644 index 0000000..784f908 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/modifier/remove_header/RemoveHeaderModifierFactory.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.modifier.remove_header; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.internal.modifier.factory.Modifier; +import com.warxim.petep.extension.internal.modifier.factory.ModifierConfigurator; +import com.warxim.petep.extension.internal.modifier.factory.ModifierData; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory; + +public final class RemoveHeaderModifierFactory extends ModifierFactory { + @Override + public String getCode() { + return "http_remove_header"; + } + + @Override + public String getName() { + return "Remove HTTP header"; + } + + @Override + public Type getConfigType() { + return RemoveHeaderData.class; + } + + @Override + public Modifier createModifier(ModifierData data) { + return new RemoveHeaderModifier(this, data); + } + + @Override + public ModifierConfigurator createConfigPane() throws IOException { + return new RemoveHeaderModifierConfigurator(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpPdu.java b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpPdu.java new file mode 100644 index 0000000..ce66728 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpPdu.java @@ -0,0 +1,83 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.pdu; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.internal.tcp.proxy.base.TcpPdu; +import com.warxim.petep.proxy.worker.Proxy; + +public abstract class HttpPdu extends TcpPdu { + protected String version; + protected Map headers; + + public HttpPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size) { + super(proxy, connection, destination, buffer, size); + headers = new HashMap<>(); + } + + public HttpPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size, + Set tags) { + super(proxy, connection, destination, buffer, size, tags); + headers = new HashMap<>(); + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public Map getHeaders() { + return headers; + } + + public void addHeaders(Map headers) { + this.headers.putAll(headers); + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public void addHeader(String name, String value) { + headers.put(name, value); + } + + public void removeHeader(String name) { + headers.remove(name); + } + + public String getHeader(String name) { + return headers.get(name); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpRequestPdu.java b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpRequestPdu.java new file mode 100644 index 0000000..2c115d4 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpRequestPdu.java @@ -0,0 +1,77 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.pdu; + +import java.util.Set; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.proxy.worker.Proxy; + +public final class HttpRequestPdu extends HttpPdu { + private String method; + private String path; + + public HttpRequestPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size) { + super(proxy, connection, destination, buffer, size); + } + + public HttpRequestPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size, + Set tags) { + super(proxy, connection, destination, buffer, size, tags); + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + @Override + public PDU copy() { + HttpRequestPdu pdu = new HttpRequestPdu(proxy, connection, destination, buffer.clone(), size); + + pdu.addTags(tags); + + pdu.setMethod(method); + pdu.setPath(path); + pdu.setVersion(version); + pdu.addHeaders(headers); + + return pdu; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpResponsePdu.java b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpResponsePdu.java new file mode 100644 index 0000000..3b00eec --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpResponsePdu.java @@ -0,0 +1,77 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.pdu; + +import java.util.Set; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.proxy.worker.Proxy; + +public final class HttpResponsePdu extends HttpPdu { + private int statusCode; + private String statusMessage; + + public HttpResponsePdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size) { + super(proxy, connection, destination, buffer, size); + } + + public HttpResponsePdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size, + Set tags) { + super(proxy, connection, destination, buffer, size, tags); + } + + public String getStatusMessage() { + return statusMessage; + } + + public void setStatusMessage(String statusMessage) { + this.statusMessage = statusMessage; + } + + public int getStatusCode() { + return statusCode; + } + + public void setStatusCode(int statusCode) { + this.statusCode = statusCode; + } + + @Override + public PDU copy() { + HttpResponsePdu pdu = new HttpResponsePdu(proxy, connection, destination, buffer.clone(), size); + + pdu.addTags(tags); + + pdu.setStatusCode(statusCode); + pdu.setStatusMessage(statusMessage); + pdu.setVersion(version); + pdu.addHeaders(headers); + + return pdu; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpUtils.java b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpUtils.java new file mode 100644 index 0000000..a4757cd --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/pdu/HttpUtils.java @@ -0,0 +1,46 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.pdu; + +public final class HttpUtils { + private HttpUtils() {} + + public static String formatHeaderName(String name) { + char[] array = name.toCharArray(); + + array[0] = Character.toUpperCase(array[0]); + int end = array.length - 1; + for (int i = 1; i < end; ++i) { + if (array[i] == '-') { + array[i + 1] = Character.toUpperCase(array[i + 1]); + } + } + + return String.valueOf(array); + } + + public static String formatHeaderName(StringBuilder builder) { + builder.setCharAt(0, Character.toUpperCase(builder.charAt(0))); + int end = builder.length() - 1; + for (int i = 1; i < end; ++i) { + if (builder.charAt(i) == '-') { + builder.setCharAt(i + 1, Character.toUpperCase(builder.charAt(i + 1))); + } + } + return builder.toString(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/pdu/Opcode.java b/src/main/java/com/warxim/petep/extension/internal/http/pdu/Opcode.java new file mode 100644 index 0000000..f6a8411 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/pdu/Opcode.java @@ -0,0 +1,72 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.pdu; + +public enum Opcode { + CONTINUATION(0), TEXT(1), BINARY(2), NON_CONTROL_1(3), NON_CONTROL_2(4), NON_CONTROL_3( + 5), NON_CONTROL_4(6), NON_CONTROL_5(7), CLOSE(8), PING( + 9), PONG(10), CONTROL_1(11), CONTROL_2(12), CONTROL_3(13), CONTROL_4(14), CONTROL_5(15); + + private final int value; + + Opcode(int value) { + this.value = value; + } + + public final int getValue() { + return value; + } + + public static final Opcode valueOf(int value) { + switch (value) { + case 0: + return Opcode.CONTINUATION; + case 1: + return Opcode.TEXT; + case 2: + return Opcode.BINARY; + case 3: + return Opcode.NON_CONTROL_1; + case 4: + return Opcode.NON_CONTROL_2; + case 5: + return Opcode.NON_CONTROL_3; + case 6: + return Opcode.NON_CONTROL_4; + case 7: + return Opcode.NON_CONTROL_5; + case 8: + return Opcode.CLOSE; + case 9: + return Opcode.PING; + case 10: + return Opcode.PONG; + case 11: + return Opcode.CONTROL_1; + case 12: + return Opcode.CONTROL_2; + case 13: + return Opcode.CONTROL_3; + case 14: + return Opcode.CONTROL_4; + case 15: + return Opcode.CONTROL_5; + default: + return null; + } + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/pdu/WebSocketPdu.java b/src/main/java/com/warxim/petep/extension/internal/http/pdu/WebSocketPdu.java new file mode 100644 index 0000000..1d71456 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/pdu/WebSocketPdu.java @@ -0,0 +1,133 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.pdu; + +import java.util.Set; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.internal.tcp.proxy.base.TcpPdu; +import com.warxim.petep.proxy.worker.Proxy; + +public final class WebSocketPdu extends TcpPdu { + private boolean isFinal; + + private boolean isRsv1; + private boolean isRsv2; + private boolean isRsv3; + + private Opcode opcode; + + private boolean isMasked; + private byte[] mask; + + public WebSocketPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size) { + super(proxy, connection, destination, buffer, size); + } + + public WebSocketPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size, + Set tags) { + super(proxy, connection, destination, buffer, size, tags); + } + + public boolean isFinal() { + return isFinal; + } + + public void setFinal(boolean isFinal) { + this.isFinal = isFinal; + } + + public Opcode getOpcode() { + return opcode; + } + + public void setOpcode(Opcode opcode) { + this.opcode = opcode; + } + + public boolean isRsv1() { + return isRsv1; + } + + public void setRsv1(boolean isRsv1) { + this.isRsv1 = isRsv1; + } + + public boolean isRsv2() { + return isRsv2; + } + + public void setRsv2(boolean isRsv2) { + this.isRsv2 = isRsv2; + } + + public boolean isRsv3() { + return isRsv3; + } + + public void setRsv3(boolean isRsv3) { + this.isRsv3 = isRsv3; + } + + public boolean isMasked() { + return isMasked; + } + + public void setMasked(boolean isMasked) { + this.isMasked = isMasked; + } + + public byte[] getMask() { + return mask; + } + + public void setMask(byte[] mask) { + this.mask = mask; + } + + @Override + public WebSocketPdu copy() { + WebSocketPdu pdu = new WebSocketPdu(proxy, connection, destination, buffer.clone(), size); + + pdu.addTags(tags); + + pdu.setFinal(isFinal); + + pdu.setRsv1(isRsv1); + pdu.setRsv2(isRsv2); + pdu.setRsv3(isRsv3); + + pdu.setOpcode(opcode); + + pdu.setMasked(isMasked); + if (isMasked) { + pdu.setMask(mask.clone()); + } + + return pdu; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpConnection.java b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpConnection.java new file mode 100644 index 0000000..b75b0e6 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpConnection.java @@ -0,0 +1,161 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.proxy; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.nio.charset.Charset; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.internal.http.pdu.HttpPdu; +import com.warxim.petep.extension.internal.http.pdu.HttpRequestPdu; +import com.warxim.petep.extension.internal.http.pdu.HttpResponsePdu; +import com.warxim.petep.extension.internal.http.pdu.Opcode; +import com.warxim.petep.extension.internal.http.pdu.WebSocketPdu; +import com.warxim.petep.extension.internal.http.reader.HttpRequestReader; +import com.warxim.petep.extension.internal.http.reader.HttpResponseReader; +import com.warxim.petep.extension.internal.http.reader.PduReader; +import com.warxim.petep.extension.internal.http.reader.WebSocketReader; +import com.warxim.petep.extension.internal.http.writer.HttpRequestWriter; +import com.warxim.petep.extension.internal.http.writer.HttpResponseWriter; +import com.warxim.petep.extension.internal.http.writer.PduWriter; +import com.warxim.petep.extension.internal.http.writer.WebSocketWriter; +import com.warxim.petep.extension.internal.tcp.proxy.base.TcpConnection; +import com.warxim.petep.proxy.worker.Proxy; + +/** HTTP connection. */ +public final class HttpConnection extends TcpConnection { + /** TCP connection constructor. */ + public HttpConnection(int id, Proxy proxy, Socket socket) { + super(id, proxy, socket); + } + + @Override + protected void readFromClient() { + try (InputStream in = socketClient.getInputStream()) { + PduReader reader = new HttpRequestReader(in, getConfig().getBufferSize(), + Charset.forName(getConfig().getCharset())); + + PDU pdu; + while ((pdu = reader.read()) != null) { + pdu.setProxy(proxy); + pdu.setConnection(this); + + if (pdu instanceof HttpRequestPdu) { + String temp = ((HttpRequestPdu) pdu).getHeader("Upgrade"); + if (temp != null && "websocket".equals(temp)) { + reader = new WebSocketReader(in, PduDestination.SERVER); + // Do not support any extensions. + ((HttpPdu) pdu).removeHeader("Sec-WebSocket-Extensions"); + } + } + + process(pdu); + } + } catch (IOException e) { + // Closed + } + } + + @Override + protected void readFromServer() { + try (InputStream in = socketServer.getInputStream()) { + PduReader reader = new HttpResponseReader(in, getConfig().getBufferSize(), + Charset.forName(getConfig().getCharset())); + + PDU pdu; + while ((pdu = reader.read()) != null) { + pdu.setProxy(proxy); + pdu.setConnection(this); + + if (pdu instanceof HttpResponsePdu) { + // HTTP + String temp = ((HttpResponsePdu) pdu).getHeader("Upgrade"); + if (temp != null && "websocket".equals(temp)) { + reader = new WebSocketReader(in, PduDestination.CLIENT); + } + } else { + // WebSockets + if (((WebSocketPdu) pdu).getOpcode() == Opcode.CLOSE) { + socketServer.close(); + } + } + + process(pdu); + } + } catch (IOException e) { + // Closed + } + } + + @Override + protected void writeToClient() { + PDU pdu; + + try (OutputStream out = socketClient.getOutputStream()) { + PduWriter writer = new HttpResponseWriter(out); + + // Read bytes to buffer and send it to out stream + while ((pdu = queueS2C.take()) != null) { + writer.write(pdu); + + if (pdu instanceof HttpResponsePdu) { + // HTTP + String temp = ((HttpResponsePdu) pdu).getHeader("Upgrade"); + if (temp != null && "websocket".equals(temp)) { + writer = new WebSocketWriter(out); + } + } else { + // WebSockets + if (((WebSocketPdu) pdu).getOpcode() == Opcode.CLOSE) { + socketClient.close(); + } + } + } + } catch (IOException e) { + // Closed socket + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + @Override + protected void writeToServer() { + PDU pdu; + + try (OutputStream out = socketServer.getOutputStream()) { + PduWriter writer = new HttpRequestWriter(out); + // Read bytes to buffer and send it to out stream + while ((pdu = queueC2S.take()) != null) { + writer.write(pdu); + + if (pdu instanceof HttpRequestPdu) { + String temp = ((HttpRequestPdu) pdu).getHeader("Upgrade"); + if (temp != null && "websocket".equals(temp)) { + writer = new WebSocketWriter(out); + } + } + } + } catch (IOException e) { + // Closed socket + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxy.java b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxy.java new file mode 100644 index 0000000..773bc87 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxy.java @@ -0,0 +1,37 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.proxy; + +import java.net.Socket; +import com.warxim.petep.extension.internal.tcp.TcpConfig; +import com.warxim.petep.extension.internal.tcp.proxy.base.TcpConnection; +import com.warxim.petep.extension.internal.tcp.proxy.base.TcpProxy; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.proxy.module.ProxyModule; + +/** HTTP Proxy. */ +public final class HttpProxy extends TcpProxy { + /** Http proxy constructor. */ + public HttpProxy(ProxyModule module, PetepHelper helper, TcpConfig config) { + super(module, helper, config); + } + + @Override + protected TcpConnection createConnection(Socket socket) { + return new HttpConnection(connectionManager.nextId(), this, socket); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxyModule.java b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxyModule.java new file mode 100644 index 0000000..cd490ea --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxyModule.java @@ -0,0 +1,54 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.proxy; + +import com.warxim.petep.extension.internal.tcp.TcpConfig; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.persistence.Configurable; +import com.warxim.petep.proxy.factory.ProxyModuleFactory; +import com.warxim.petep.proxy.module.ProxyModule; +import com.warxim.petep.proxy.worker.Proxy; + +/** TCP proxy module. */ +public final class HttpProxyModule extends ProxyModule implements Configurable { + private TcpConfig config; + + /** TCP proxy module constructor. */ + public HttpProxyModule( + ProxyModuleFactory factory, + String code, + String name, + String description, + boolean enabled) { + super(factory, code, name, description, enabled); + } + + @Override + public Proxy createProxy(PetepHelper helper) { + return new HttpProxy(this, helper, config); + } + + @Override + public TcpConfig saveConfig() { + return config; + } + + @Override + public void loadConfig(TcpConfig config) { + this.config = config; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxyModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxyModuleFactory.java new file mode 100644 index 0000000..a4d9eb3 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/proxy/HttpProxyModuleFactory.java @@ -0,0 +1,211 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.proxy; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.internal.http.gui.HttpMetadataPane; +import com.warxim.petep.extension.internal.http.pdu.HttpRequestPdu; +import com.warxim.petep.extension.internal.http.pdu.HttpResponsePdu; +import com.warxim.petep.extension.internal.http.pdu.Opcode; +import com.warxim.petep.extension.internal.http.pdu.WebSocketPdu; +import com.warxim.petep.extension.internal.tcp.TcpConfig; +import com.warxim.petep.extension.internal.tcp.TcpConfigurator; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.gui.component.PduMetadataPane; +import com.warxim.petep.persistence.Configurator; +import com.warxim.petep.proxy.factory.ProxyModuleFactory; +import com.warxim.petep.proxy.module.ProxyModule; +import com.warxim.petep.proxy.serizalization.ProxyDeserializer; +import com.warxim.petep.proxy.serizalization.ProxySerializer; +import com.warxim.petep.proxy.worker.Proxy; +import com.warxim.petep.util.BytesUtils; + +/** HTTP proxy module. */ +public final class HttpProxyModuleFactory extends ProxyModuleFactory + implements Configurator, ProxySerializer, ProxyDeserializer { + /** HTTP proxy module constructor. */ + public HttpProxyModuleFactory(Extension extension) { + super(extension); + } + + @Override + public String getName() { + return "HTTP"; + } + + @Override + public String getCode() { + return "http"; + } + + @Override + public ProxyModule createModule(String code, String name, String description, boolean enabled) { + return new HttpProxyModule(this, code, name, description, enabled); + } + + @Override + public ConfigPane createConfigPane() throws IOException { + return new TcpConfigurator(); + } + + @Override + public PduMetadataPane createPduMetadataPane() throws IOException { + return new HttpMetadataPane(); + } + + @Override + public Map serializePduMetadata(PDU pdu) { + Map metadata = new HashMap<>(); + if (pdu instanceof HttpRequestPdu) { + HttpRequestPdu request = (HttpRequestPdu) pdu; + + if (request.getVersion() != null) { + metadata.put("Method", request.getMethod()); + metadata.put("Path", request.getPath()); + metadata.put("Version", request.getVersion()); + } + + for (var header : request.getHeaders().entrySet()) { + metadata.put("H-" + header.getKey(), header.getValue()); + } + + return metadata; + } else if (pdu instanceof HttpResponsePdu) { + HttpResponsePdu response = (HttpResponsePdu) pdu; + + if (response.getVersion() != null) { + metadata.put("Status-Code", String.valueOf(response.getStatusCode())); + metadata.put("Status-Message", response.getStatusMessage()); + metadata.put("Version", response.getVersion()); + } + + for (var header : response.getHeaders().entrySet()) { + metadata.put("H-" + header.getKey(), header.getValue()); + } + + return metadata; + } else if (pdu instanceof WebSocketPdu) { + WebSocketPdu websocketPdu = (WebSocketPdu) pdu; + + metadata.put("Fin", websocketPdu.isFinal() ? "1" : "0"); + metadata.put("RSV", (websocketPdu.isRsv1() ? "1" : "0") + "," + + (websocketPdu.isRsv2() ? "1" : "0") + "," + (websocketPdu.isRsv3() ? "1" : "0")); + metadata.put("Opcode", websocketPdu.getOpcode().name()); + metadata.put("Masked", websocketPdu.isMasked() ? "1" : "0"); + + if (websocketPdu.isMasked()) { + metadata.put("Mask", BytesUtils.bytesToString(websocketPdu.getMask())); + } + + return metadata; + } + + return null; + } + + @Override + public PDU deserializePdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size, + Set tags, + Map serializedMetadata) { + // WebSockets + if (serializedMetadata.containsKey("Fin")) { + WebSocketPdu pdu = new WebSocketPdu(proxy, connection, destination, buffer, size, tags); + + // FIN + pdu.setFinal(serializedMetadata.get("Fin").equals("1")); + + // RSV + String[] rsv = serializedMetadata.get("RSV").split(","); + pdu.setRsv1(rsv[0].equals("1")); + pdu.setRsv2(rsv[1].equals("1")); + pdu.setRsv3(rsv[2].equals("1")); + + pdu.setOpcode(Opcode.valueOf(serializedMetadata.get("Opcode"))); + + pdu.setMasked(serializedMetadata.get("Masked").equals("1")); + + if (pdu.isMasked()) { + pdu.setMask(BytesUtils.stringToBytes(serializedMetadata.get("Mask"))); + } + + return pdu; + } else { + // HTTP + if (destination == PduDestination.SERVER) { + HttpRequestPdu request = + new HttpRequestPdu(proxy, connection, destination, buffer, size, tags); + + for (var item : serializedMetadata.entrySet()) { + String key = item.getKey(); + + if (key.startsWith("H-")) { + request.addHeader(key.substring(2), item.getValue()); + } else if (key.equals("Method")) { + request.setMethod(item.getValue()); + } else if (key.equals("Path")) { + request.setPath(item.getValue()); + } else if (key.equals("Version")) { + request.setVersion(item.getValue()); + } + } + + return request; + } else { + HttpResponsePdu response = + new HttpResponsePdu(proxy, connection, destination, buffer, size, tags); + + for (var item : serializedMetadata.entrySet()) { + String key = item.getKey(); + + if (key.startsWith("H-")) { + response.addHeader(key.substring(2), item.getValue()); + } else if (key.equals("Status-Code")) { + response.setStatusCode(Integer.parseInt(item.getValue())); + } else if (key.equals("Status-Message")) { + response.setStatusMessage(item.getValue()); + } else if (key.equals("Version")) { + response.setVersion(item.getValue()); + } + } + + return response; + } + } + } + + @Override + public ProxySerializer getSerializer() { + return this; + } + + @Override + public ProxyDeserializer getDeserializer() { + return this; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpReader.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpReader.java new file mode 100644 index 0000000..e45b2c9 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpReader.java @@ -0,0 +1,250 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.reader; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.http.pdu.HttpPdu; +import com.warxim.petep.extension.internal.http.pdu.HttpUtils; +import com.warxim.petep.extension.internal.http.reader.state.BodyWithChunkedEncodingState; +import com.warxim.petep.extension.internal.http.reader.state.BodyWithChunkedEncodingState.ChunkedBodyStep; +import com.warxim.petep.extension.internal.http.reader.state.BodyWithContentLengthState; +import com.warxim.petep.extension.internal.http.reader.state.InternalState; + +public abstract class HttpReader extends PduReader { + protected enum HeaderStep { + HEADER_NAME, HEADER_VALUE + } + + protected final int maxLength; + protected final Charset defaultCharset; + protected InternalState internalState; + + public HttpReader(InputStream in, int maxLength, Charset defaultCharset) { + super(in); + this.maxLength = maxLength; + this.defaultCharset = defaultCharset; + } + + public abstract PDU read() throws IOException; + + protected final boolean readHeaders(HttpPdu request) throws IOException { + StringBuilder builder = new StringBuilder(); + HeaderStep step = HeaderStep.HEADER_NAME; + int currentByte; + String temp = ""; + while ((currentByte = in.read()) != -1) { + if (step == HeaderStep.HEADER_NAME) { + if (currentByte == ':') { + // Skip space. + skip(1); + + temp = HttpUtils.formatHeaderName(builder); + builder.setLength(0); + + step = HeaderStep.HEADER_VALUE; + continue; + } else if (currentByte == '\r') { // End of headers. + // Skip \n. + skip(1); + + return true; + } + } else { // HEADER_VALUE + if (currentByte == '\r') { + // Skip \n. + skip(1); + + String oldValue; + if ((oldValue = request.getHeader(temp)) != null) { + request.addHeader(temp, oldValue + ", " + builder.toString()); + } else { + request.addHeader(temp, builder.toString()); + } + builder.setLength(0); + + step = HeaderStep.HEADER_NAME; + continue; + } + } + + builder.append((char) currentByte); + } + + return false; + } + + protected final void processHeaders(HttpPdu pdu) { + // Content-Type + String value; + if ((value = pdu.getHeader("Content-Type")) != null) { + int index = value.indexOf("charset="); + if (index != -1) { + pdu.setCharset(Charset.forName(value.substring(index + 8))); + } else { + pdu.setCharset(defaultCharset); + } + } else { + pdu.setCharset(defaultCharset); + } + } + + protected final void processBodyWithContentLength(HttpPdu pdu) throws IOException { + BodyWithContentLengthState state = ((BodyWithContentLengthState) internalState); + + byte[] buffer; + if (state.getContentLength() > maxLength) { + buffer = new byte[maxLength]; + + if (state.isChunked()) { + pdu.addTag("chunk"); + } + + // We are going to read just part of the message. + state.setContentLength(state.getContentLength() - maxLength); + } else { + buffer = new byte[state.getContentLength()]; + + if (state.isChunked()) { + pdu.addTag("last_chunk"); + } + + // We are going to read the rest. + internalState = null; + } + + readNBytes(buffer, 0, buffer.length); + + pdu.setBuffer(buffer, buffer.length); + } + + protected final void processBodyWithChunkedEncoding(HttpPdu pdu) throws IOException { + BodyWithChunkedEncodingState state = (BodyWithChunkedEncodingState) internalState; + + int index = 0; + byte[] buffer = new byte[maxLength]; + StringBuilder builder = new StringBuilder(); + int currentByte; + + while (index != buffer.length) { + if (state.getChunkStep() == ChunkedBodyStep.LENGTH) { + if ((currentByte = in.read()) == -1) { + break; + } + + if (currentByte == '\r') { + // Skip \n + skip(1); + + int length = Integer.parseInt(builder.toString(), 16); + + if (length == 0) { + skip(2); + + pdu.setBuffer(buffer, index); + pdu.addTag("last_chunk"); + + // No more chunks. + internalState = null; + return; + } + + state.setChunkLength(Integer.parseInt(builder.toString(), 16)); + state.setChunkStep(ChunkedBodyStep.CHUNK); + builder.setLength(0); + } else { + builder.append((char) currentByte); + } + } else { + int remaining = maxLength - index; + if (state.getChunkLength() > remaining) { + // Not enough space. + + // Next step is to parse the rest of the chunk. + state.setChunkLength(state.getChunkLength() - remaining); + state.setChunkStep(ChunkedBodyStep.CHUNK); + + // Read part of a chunk. + readNBytes(buffer, index, remaining); + index += remaining; + + break; + } else { + // Enough space. + + // Read chunk. + readNBytes(buffer, index, state.getChunkLength()); + index += state.getChunkLength(); + + // Next step is to parse length. + state.setChunkStep(ChunkedBodyStep.LENGTH); + + // Skip \r\n + skip(2); + } + } + } + + pdu.addTag("chunk"); + + pdu.setBuffer(buffer, index); + } + + protected final void readBody(HttpPdu pdu) throws IOException { + if (internalState == null) { + // Determine type of body. + String temp = pdu.getHeader("Content-Length"); + if (temp != null) { + int length = Integer.parseInt(temp); + + internalState = new BodyWithContentLengthState(length); + + // Length is above the limit. Switching to chunked encoding, so that the PDUs will be + // editable separately (impossible with content-length). + if (length > maxLength) { + pdu.removeHeader("Content-Length"); + pdu.addHeader("Transfer-Encoding", "chunked"); + ((BodyWithContentLengthState) internalState).setChunked(true); + } + } else if ((temp = pdu.getHeader("Transfer-Encoding")) != null && temp.equals("chunked")) { + internalState = new BodyWithChunkedEncodingState(); + } else { + pdu.setBuffer(new byte[0], 0); + } + } + + if (internalState instanceof BodyWithContentLengthState) { + processBodyWithContentLength(pdu); + } else if (internalState instanceof BodyWithChunkedEncodingState) { + processBodyWithChunkedEncoding(pdu); + } + } + + protected final void skip(int n) throws IOException { + if (in.skip(n) != n) { + throw new IOException("Could not skip bytes!"); + } + } + + protected final void readNBytes(byte[] buffer, int offset, int length) throws IOException { + if (in.readNBytes(buffer, offset, length) != length) { + throw new IOException("Could not skip bytes!"); + } + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpRequestReader.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpRequestReader.java new file mode 100644 index 0000000..404cacd --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpRequestReader.java @@ -0,0 +1,97 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.reader; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.internal.http.pdu.HttpRequestPdu; + +public final class HttpRequestReader extends HttpReader { + protected enum RequestLineState { + METHOD, PATH, VERSION + } + + public HttpRequestReader(InputStream in, int maxLength, Charset defaultCharset) { + super(in, maxLength, defaultCharset); + } + + @Override + public HttpRequestPdu read() throws IOException { + HttpRequestPdu request = new HttpRequestPdu(null, null, PduDestination.SERVER, null, 0); + + if (internalState == null) { + if (!readRequestLine(request) || !readHeaders(request)) { + return null; + } + + processHeaders(request); + + readBody(request); + } else { + readBody(request); + } + + return request; + } + + private boolean readRequestLine(HttpRequestPdu request) throws IOException { + RequestLineState state = RequestLineState.METHOD; + + StringBuilder builder = new StringBuilder(); + + int currentByte; + while ((currentByte = in.read()) != -1) { + switch (state) { + case METHOD: + if (currentByte == ' ') { + request.setMethod(builder.toString()); + builder.setLength(0); + state = RequestLineState.PATH; + break; + } + + builder.append((char) currentByte); + break; + case PATH: + if (currentByte == ' ') { + request.setPath(builder.toString()); + builder.setLength(0); + state = RequestLineState.VERSION; + break; + } + + builder.append((char) currentByte); + break; + case VERSION: + if (currentByte == '\r') { + // Skip \n. + skip(1); + + request.setVersion(builder.toString()); + return true; + } + + builder.append((char) currentByte); + break; + } + } + + return false; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpResponseReader.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpResponseReader.java new file mode 100644 index 0000000..b5213f8 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/HttpResponseReader.java @@ -0,0 +1,96 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.reader; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.internal.http.pdu.HttpResponsePdu; + +public final class HttpResponseReader extends HttpReader { + protected enum StatusLineState { + VERSION, STATUS_CODE, STATUS_MESSAGE + } + + public HttpResponseReader(InputStream in, int maxLength, Charset defaultCharset) { + super(in, maxLength, defaultCharset); + } + + @Override + public HttpResponsePdu read() throws IOException { + HttpResponsePdu response = new HttpResponsePdu(null, null, PduDestination.CLIENT, null, 0); + + if (internalState == null) { + if (!readStatusLine(response) || !readHeaders(response)) { + return null; + } + + processHeaders(response); + + readBody(response); + } else { + readBody(response); + } + + return response; + } + + private boolean readStatusLine(HttpResponsePdu response) throws IOException { + StatusLineState state = StatusLineState.VERSION; + + StringBuilder builder = new StringBuilder(); + + int currentByte; + while ((currentByte = in.read()) != -1) { + switch (state) { + case VERSION: + if (currentByte == ' ') { + response.setVersion(builder.toString()); + builder.setLength(0); + state = StatusLineState.STATUS_CODE; + break; + } + + builder.append((char) currentByte); + break; + case STATUS_CODE: + if (currentByte == ' ') { + response.setStatusCode(Integer.parseInt(builder.toString())); + builder.setLength(0); + state = StatusLineState.STATUS_MESSAGE; + break; + } + + builder.append((char) currentByte); + break; + case STATUS_MESSAGE: + if (currentByte == '\r') { + // Skip \n. + skip(1); + + response.setStatusMessage(builder.toString()); + return true; + } + + builder.append((char) currentByte); + break; + } + } + return false; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/PduReader.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/PduReader.java new file mode 100644 index 0000000..a754bc9 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/PduReader.java @@ -0,0 +1,31 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.reader; + +import java.io.IOException; +import java.io.InputStream; +import com.warxim.petep.core.pdu.PDU; + +public abstract class PduReader { + protected final InputStream in; + + public PduReader(InputStream in) { + this.in = in; + } + + public abstract PDU read() throws IOException; +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/WebSocketReader.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/WebSocketReader.java new file mode 100644 index 0000000..42407ab --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/WebSocketReader.java @@ -0,0 +1,127 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.reader; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.internal.http.pdu.Opcode; +import com.warxim.petep.extension.internal.http.pdu.WebSocketPdu; + +public final class WebSocketReader extends PduReader { + private final PduDestination destination; + + public WebSocketReader(InputStream in, PduDestination destination) { + super(in); + this.destination = destination; + } + + public WebSocketPdu read() throws IOException { + WebSocketPdu pdu = new WebSocketPdu(null, null, destination, null, 0); + + readFragment(pdu); + + // Set UTF8 for text. + if (pdu.getOpcode() == Opcode.TEXT) { + pdu.setCharset(StandardCharsets.UTF_8); + } + + return pdu; + } + + private void readFragment(WebSocketPdu pdu) throws IOException { + int currentByte; + + currentByte = in.read(); + if (currentByte == -1) { + throw new IOException("Could not read first WebSocket byte."); + } + + // FIN + pdu.setFinal((currentByte & 0b1000_0000) != 0); + + // RSV1 + pdu.setRsv1((currentByte & 0b0100_0000) != 0); + + // RSV2 + pdu.setRsv2((currentByte & 0b0010_0000) != 0); + + // RSV3 + pdu.setRsv3((currentByte & 0b0001_0000) != 0); + + // OPCODE + pdu.setOpcode(Opcode.valueOf(currentByte & 0b0000_1111)); + + currentByte = in.read(); + if (currentByte == -1) { + throw new IOException("Could not read second WebSocket byte."); + } + + // MASKED + pdu.setMasked((currentByte & 0b1000_0000) != 0); + + // LENGTH + int length; + currentByte = currentByte & 0b0111_1111; + if (currentByte <= 125) { + // It's the length! + length = currentByte; + } else if (currentByte == 126) { + // The next 16 bits are the length. + currentByte = in.read(); + if (currentByte == -1) { + throw new IOException("Could not read WebSocket length."); + } + length = (currentByte & 0xFF) << 8; + + currentByte = in.read(); + if (currentByte == -1) { + throw new IOException("Could not read WebSocket length."); + } + length |= (currentByte & 0xFF); + } else { + // The next 64 bits are the length. + throw new IOException("WebSocket message is too large."); + } + + byte[] data = new byte[length]; + + // MASK + if (pdu.isMasked()) { + byte[] mask = in.readNBytes(4); + + if (mask.length != 4) { + throw new IOException("Could not read WebSocket mask."); + } + + pdu.setMask(mask); + + if (in.readNBytes(data, 0, length) != length) { + throw new IOException("Could not read WebSocket data."); + } + + for (int i = 0; i < data.length; ++i) { + data[i] ^= mask[i & 0x3]; + } + } else if (in.readNBytes(data, 0, length) != length) { + throw new IOException("Could not read WebSocket data."); + } + + pdu.setBuffer(data, length); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/state/BodyWithChunkedEncodingState.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/state/BodyWithChunkedEncodingState.java new file mode 100644 index 0000000..d19b045 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/state/BodyWithChunkedEncodingState.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.reader.state; + +public final class BodyWithChunkedEncodingState extends InternalState { + public enum ChunkedBodyStep { + LENGTH, CHUNK + } + + private int chunkLength; + private ChunkedBodyStep step; + + public BodyWithChunkedEncodingState() { + this.chunkLength = -1; + this.step = ChunkedBodyStep.LENGTH; + } + + public int getChunkLength() { + return chunkLength; + } + + public int decreaseChunkLength() { + return --chunkLength; + } + + public void setChunkLength(int chunkLength) { + this.chunkLength = chunkLength; + } + + public ChunkedBodyStep getChunkStep() { + return step; + } + + public void setChunkStep(ChunkedBodyStep step) { + this.step = step; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/state/BodyWithContentLengthState.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/state/BodyWithContentLengthState.java new file mode 100644 index 0000000..ab8cc58 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/state/BodyWithContentLengthState.java @@ -0,0 +1,43 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.reader.state; + +public final class BodyWithContentLengthState extends InternalState { + private int contentLength; + private boolean chunked; + + public BodyWithContentLengthState(int contentLength) { + this.contentLength = contentLength; + this.chunked = false; + } + + public int getContentLength() { + return contentLength; + } + + public void setContentLength(int contentLength) { + this.contentLength = contentLength; + } + + public boolean isChunked() { + return chunked; + } + + public void setChunked(boolean chunked) { + this.chunked = chunked; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/reader/state/InternalState.java b/src/main/java/com/warxim/petep/extension/internal/http/reader/state/InternalState.java new file mode 100644 index 0000000..f2e7025 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/reader/state/InternalState.java @@ -0,0 +1,20 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.reader.state; + +public abstract class InternalState { +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderData.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderData.java new file mode 100644 index 0000000..91c95b7 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderData.java @@ -0,0 +1,37 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.tagger.has_header; + +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; + +public final class HasHeaderData extends TagSubruleData { + private final String name; + private final String value; + + public HasHeaderData(String name, String value) { + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubrule.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubrule.java new file mode 100644 index 0000000..9703d52 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubrule.java @@ -0,0 +1,46 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.tagger.has_header; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.http.pdu.HttpPdu; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class HasHeaderSubrule extends TagSubrule { + public HasHeaderSubrule(TagSubruleFactory factory, TagSubruleData data) { + super(factory, data); + } + + @Override + public boolean test(PDU pdu) { + if (!(pdu instanceof HttpPdu)) { + return false; + } + + String value = ((HttpPdu) pdu).getHeader(((HasHeaderData) data).getName()); + + return value != null && value.equals(((HasHeaderData) data).getValue()); + } + + @Override + public String toString() { + return "Has header " + ((HasHeaderData) data).getName() + " = " + + ((HasHeaderData) data).getValue(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubruleConfigurator.java new file mode 100644 index 0000000..4548772 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubruleConfigurator.java @@ -0,0 +1,61 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.tagger.has_header; + +import java.io.IOException; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.fxml.FXML; +import javafx.scene.control.TextField; + +public final class HasHeaderSubruleConfigurator extends TagSubruleConfigurator { + @FXML + private TextField nameInput; + @FXML + private TextField valueInput; + + public HasHeaderSubruleConfigurator() throws IOException { + super("/fxml/extension/internal/http/tagger/HasHeader.fxml"); + } + + @Override + public TagSubruleData getConfig() { + return new HasHeaderData(nameInput.getText(), valueInput.getText()); + } + + @Override + public void setConfig(TagSubruleData config) { + nameInput.setText(((HasHeaderData) config).getName()); + valueInput.setText(((HasHeaderData) config).getValue()); + } + + @Override + public boolean isValid() { + if (nameInput.getText().length() == 0) { + Dialogs.createErrorDialog("Header name required", "You have to enter header name."); + return false; + } + + if (valueInput.getText().length() == 0) { + Dialogs.createErrorDialog("Header value required", "You have to enter header value."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubruleFactory.java new file mode 100644 index 0000000..7bfd469 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/has_header/HasHeaderSubruleFactory.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.tagger.has_header; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class HasHeaderSubruleFactory extends TagSubruleFactory { + @Override + public String getCode() { + return "header"; + } + + @Override + public String getName() { + return "Has header ..."; + } + + @Override + public TagSubrule createSubrule(TagSubruleData data) { + return new HasHeaderSubrule(this, data); + } + + @Override + public TagSubruleConfigurator createConfigPane() throws IOException { + return new HasHeaderSubruleConfigurator(); + } + + @Override + public Type getConfigType() { + return HasHeaderData.class; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_http/IsHttpSubrule.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_http/IsHttpSubrule.java new file mode 100644 index 0000000..59f2b3d --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_http/IsHttpSubrule.java @@ -0,0 +1,39 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.tagger.is_http; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.http.pdu.HttpPdu; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class IsHttpSubrule extends TagSubrule { + public IsHttpSubrule(TagSubruleFactory factory, TagSubruleData data) { + super(factory, data); + } + + @Override + public boolean test(PDU pdu) { + return pdu instanceof HttpPdu; + } + + @Override + public String toString() { + return "Is HTTP"; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_http/IsHttpSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_http/IsHttpSubruleFactory.java new file mode 100644 index 0000000..66fd097 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_http/IsHttpSubruleFactory.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.tagger.is_http; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class IsHttpSubruleFactory extends TagSubruleFactory { + @Override + public String getCode() { + return "is_http"; + } + + @Override + public String getName() { + return "Is HTTP?"; + } + + @Override + public TagSubrule createSubrule(TagSubruleData data) { + return new IsHttpSubrule(this, data); + } + + @Override + public TagSubruleConfigurator createConfigPane() throws IOException { + return null; + } + + @Override + public Type getConfigType() { + return null; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_websocket/IsWebSocketSubrule.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_websocket/IsWebSocketSubrule.java new file mode 100644 index 0000000..14c5538 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_websocket/IsWebSocketSubrule.java @@ -0,0 +1,39 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.tagger.is_websocket; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.http.pdu.WebSocketPdu; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class IsWebSocketSubrule extends TagSubrule { + public IsWebSocketSubrule(TagSubruleFactory factory, TagSubruleData data) { + super(factory, data); + } + + @Override + public boolean test(PDU pdu) { + return pdu instanceof WebSocketPdu; + } + + @Override + public String toString() { + return "Is WebSocket"; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_websocket/IsWebSocketSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_websocket/IsWebSocketSubruleFactory.java new file mode 100644 index 0000000..1ee5105 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/tagger/is_websocket/IsWebSocketSubruleFactory.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.tagger.is_websocket; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class IsWebSocketSubruleFactory extends TagSubruleFactory { + @Override + public String getCode() { + return "is_websocket"; + } + + @Override + public String getName() { + return "Is WebSocket?"; + } + + @Override + public TagSubrule createSubrule(TagSubruleData data) { + return new IsWebSocketSubrule(this, data); + } + + @Override + public TagSubruleConfigurator createConfigPane() throws IOException { + return null; + } + + @Override + public Type getConfigType() { + return null; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpRequestWriter.java b/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpRequestWriter.java new file mode 100644 index 0000000..ba8d967 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpRequestWriter.java @@ -0,0 +1,49 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.writer; + +import java.io.IOException; +import java.io.OutputStream; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.http.pdu.HttpPdu; +import com.warxim.petep.extension.internal.http.pdu.HttpRequestPdu; + +public final class HttpRequestWriter extends HttpWriter { + public HttpRequestWriter(OutputStream out) { + super(out); + } + + @Override + public void write(PDU request) throws IOException { + writeRequestLine((HttpRequestPdu) request); + writeHeaders((HttpPdu) request); + writeBody((HttpPdu) request); + } + + private void writeRequestLine(HttpRequestPdu request) throws IOException { + if (request.getVersion() == null) { + return; + } + + out.write(request.getMethod().getBytes()); + out.write(' '); + out.write(request.getPath().getBytes()); + out.write(' '); + out.write(request.getVersion().getBytes()); + out.write("\r\n".getBytes()); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpResponseWriter.java b/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpResponseWriter.java new file mode 100644 index 0000000..fce7ca2 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpResponseWriter.java @@ -0,0 +1,49 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.writer; + +import java.io.IOException; +import java.io.OutputStream; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.http.pdu.HttpPdu; +import com.warxim.petep.extension.internal.http.pdu.HttpResponsePdu; + +public final class HttpResponseWriter extends HttpWriter { + public HttpResponseWriter(OutputStream out) { + super(out); + } + + @Override + public void write(PDU response) throws IOException { + writeStatusLine((HttpResponsePdu) response); + writeHeaders((HttpPdu) response); + writeBody((HttpPdu) response); + } + + private void writeStatusLine(HttpResponsePdu response) throws IOException { + if (response.getVersion() == null) { + return; + } + + out.write(response.getVersion().getBytes()); + out.write(' '); + out.write(String.valueOf(response.getStatusCode()).getBytes()); + out.write(' '); + out.write(response.getStatusMessage().getBytes()); + out.write("\r\n".getBytes()); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpWriter.java b/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpWriter.java new file mode 100644 index 0000000..b04ae70 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/writer/HttpWriter.java @@ -0,0 +1,68 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.writer; + +import java.io.IOException; +import java.io.OutputStream; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.http.pdu.HttpPdu; + +public abstract class HttpWriter extends PduWriter { + public HttpWriter(OutputStream out) { + super(out); + } + + public abstract void write(PDU pdu) throws IOException; + + protected final void writeHeaders(HttpPdu pdu) throws IOException { + if (pdu.getHeaders().isEmpty()) { + return; + } + + if (pdu.getHeader("Content-Length") != null) { + pdu.addHeader("Content-Length", String.valueOf(pdu.getSize())); + } + + for (var header : pdu.getHeaders().entrySet()) { + out.write(header.getKey().getBytes()); + out.write(": ".getBytes()); + out.write(header.getValue().getBytes()); + out.write("\r\n".getBytes()); + } + + out.write("\r\n".getBytes()); + } + + protected final void writeBody(HttpPdu pdu) throws IOException { + if (pdu.getSize() == 0) { + return; + } + + if (pdu.hasTag("chunk") || pdu.hasTag("last_chunk")) { + out.write(Integer.toHexString(pdu.getSize()).getBytes()); + out.write("\r\n".getBytes()); + out.write(pdu.getBuffer(), 0, pdu.getSize()); + out.write("\r\n".getBytes()); + + if (pdu.hasTag("last_chunk")) { + out.write("0\r\n\r\n".getBytes()); + } + } else { + out.write(pdu.getBuffer(), 0, pdu.getSize()); + } + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/writer/PduWriter.java b/src/main/java/com/warxim/petep/extension/internal/http/writer/PduWriter.java new file mode 100644 index 0000000..3934912 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/writer/PduWriter.java @@ -0,0 +1,31 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.writer; + +import java.io.IOException; +import java.io.OutputStream; +import com.warxim.petep.core.pdu.PDU; + +public abstract class PduWriter { + protected final OutputStream out; + + public PduWriter(OutputStream out) { + this.out = out; + } + + public abstract void write(PDU pdu) throws IOException; +} diff --git a/src/main/java/com/warxim/petep/extension/internal/http/writer/WebSocketWriter.java b/src/main/java/com/warxim/petep/extension/internal/http/writer/WebSocketWriter.java new file mode 100644 index 0000000..d243274 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/http/writer/WebSocketWriter.java @@ -0,0 +1,97 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.http.writer; + +import java.io.IOException; +import java.io.OutputStream; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.http.pdu.WebSocketPdu; + +public final class WebSocketWriter extends PduWriter { + public WebSocketWriter(OutputStream out) { + super(out); + } + + public void write(PDU pdu) throws IOException { + writeFragment((WebSocketPdu) pdu); + } + + private void writeFragment(WebSocketPdu pdu) throws IOException { + int currentByte = 0; + + // FIN + if (pdu.isFinal()) { + currentByte |= 0b1000_0000; + } + + // RSV1 + if (pdu.isRsv1()) { + currentByte |= 0b0100_0000; + } + + // RSV2 + if (pdu.isRsv2()) { + currentByte |= 0b0010_0000; + } + + // RSV3 + if (pdu.isRsv3()) { + currentByte |= 0b0001_0000; + } + + // OPCODE + currentByte |= pdu.getOpcode().getValue() & 0b0000_1111; + + out.write(currentByte); + + // MASKED + if (pdu.isMasked()) { + currentByte = 0b1000_0000; + } else { + currentByte = 0b0000_0000; + } + + // LENGTH + int length = pdu.getSize(); + if (length <= 125) { + currentByte |= length & 0b0111_1111; + out.write(currentByte); + } else { + currentByte |= 126; + out.write(currentByte); + + out.write((length >> 8) & 0xFF); + out.write(length & 0xFF); + } + + if (pdu.isMasked()) { + byte[] mask = pdu.getMask(); + + out.write(mask, 0, 4); + + byte[] data = pdu.getBuffer(); + + for (int i = 0; i < length; ++i) { + data[i] ^= mask[i & 0x3]; + } + + out.write(data, 0, length); + } else { + out.write(pdu.getBuffer(), 0, length); + } + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerConfig.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerConfig.java new file mode 100644 index 0000000..5275013 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerConfig.java @@ -0,0 +1,31 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.logger; + +/** Logger configuration. */ +public final class LoggerConfig { + private final String path; + + /** Logger configuration constructor. */ + public LoggerConfig(String path) { + this.path = path; + } + + public String getPath() { + return path; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerConfigurator.java new file mode 100644 index 0000000..55de0f6 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerConfigurator.java @@ -0,0 +1,91 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.logger; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.util.FileUtils; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.TextField; +import javafx.stage.FileChooser; + +/** Logger configurator. */ +public class LoggerConfigurator extends ConfigPane { + + @FXML + private TextField pathInput; + + /** Logger configurator constructor. */ + public LoggerConfigurator() throws IOException { + super("/fxml/extension/internal/logger/LoggerConfigurator.fxml"); + } + + @Override + public LoggerConfig getConfig() { + return new LoggerConfig(pathInput.getText()); + } + + @Override + public void setConfig(LoggerConfig config) { + pathInput.setText(config.getPath()); + } + + @Override + public boolean isValid() { + if (pathInput.getText().length() == 0) { + Dialogs.createErrorDialog("Path required", "You have to enter path."); + return false; + } + + return true; + } + + @FXML + private void onFileOpenButtonClick(ActionEvent event) { + // Choose log file + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Log file"); + + if (pathInput.getText().isBlank()) { + fileChooser.setInitialDirectory(new File(FileUtils.getProjectDirectory())); + } else { + File temp = new File(FileUtils.getProjectFileAbsolutePath(pathInput.getText())); + fileChooser.setInitialDirectory(temp.getParentFile()); + fileChooser.setInitialFileName(temp.getName()); + } + + fileChooser.getExtensionFilters() + .addAll(new FileChooser.ExtensionFilter("Log file (*.log)", "*.log"), + new FileChooser.ExtensionFilter("Text file (*.txt)", "*.txt"), + new FileChooser.ExtensionFilter("All files (*.*)", "*.*")); + + File file = fileChooser.showSaveDialog(null); + if (file == null) { + return; + } + + pathInput.setText(Paths.get(FileUtils.getProjectDirectory()) + .toAbsolutePath() + .relativize(Paths.get(file.getAbsolutePath())) + .toString() + .replace('\\', '/')); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerExtension.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerExtension.java new file mode 100644 index 0000000..d0b5d4a --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerExtension.java @@ -0,0 +1,123 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.logger; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.Logger; +import com.warxim.petep.core.listener.PetepListener; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.helper.GuiHelper; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.worker.Interceptor; + +/** Logger extension. */ +public final class LoggerExtension extends Extension { + private ExecutorService executor; + + /** Logger extension constructor. */ + public LoggerExtension(String path) { + super(path); + + executor = null; + + Logger.getGlobal().info("Logger extension created."); + } + + @Override + public void init(ExtensionHelper helper) { + helper.registerInterceptorModuleFactory(new LoggerInterceptorModuleFactory(this)); + + helper.registerPetepListener(new PetepListener() { + /** Creates workfer for each log file. */ + private void processInterceptors( + List interceptors, + Map workers) { + for (Interceptor interceptor : interceptors) { + if (interceptor instanceof LoggerInterceptor) { + // Get or create a log worker + LoggerWorker worker = workers.computeIfAbsent( + ((LoggerInterceptorModule) interceptor.getModule()).getConfig().getPath(), + LoggerWorker::new); + + ((LoggerInterceptor) interceptor).setWorker(worker); + } + } + } + + @Override + public void beforePrepare(PetepHelper helper) { + Map workers = new HashMap<>(); + + // Process interceptors. + + processInterceptors(helper.getInterceptorsC2S(), workers); + processInterceptors(helper.getInterceptorsS2C(), workers); + + if (workers.isEmpty()) { + return; + } + + // Start workers. + executor = Executors.newCachedThreadPool(); + + for (LoggerWorker worker : workers.values()) { + executor.submit(worker); + } + } + + @Override + public void afterStop(PetepHelper helper) { + if (executor != null) { + executor.shutdownNow(); + executor = null; + } + } + }); + + Logger.getGlobal().info("Logger extension registered."); + } + + @Override + public String getCode() { + return "logger"; + } + + @Override + public String getName() { + return "Logger"; + } + + @Override + public String getDescription() { + return "Internal logger extension."; + } + + @Override + public String getVersion() { + return "1.0"; + } + + @Override + public void initGui(GuiHelper helper) { + helper.registerGuide(new LoggerGuide()); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerGuide.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerGuide.java new file mode 100644 index 0000000..983422d --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerGuide.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.logger; + +import com.warxim.petep.gui.guide.Guide; + +/** Logger guide. */ +public final class LoggerGuide extends Guide { + @Override + public String getTitle() { + return "Logger"; + } + + @Override + public String getHtml() { + return loadHtmlResource("/html/guide/internal/LoggerGuide.html"); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptor.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptor.java new file mode 100644 index 0000000..0e3d513 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptor.java @@ -0,0 +1,54 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.logger; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.worker.Interceptor; + +/** Logger interceptor. */ +public final class LoggerInterceptor extends Interceptor { + private LoggerWorker worker; + + /** Logger interceptor constructor. */ + public LoggerInterceptor(int id, LoggerInterceptorModule module, PetepHelper helper) { + super(id, module, helper); + } + + @Override + public boolean intercept(PDU pdu) { + if (!pdu.hasTag("no_log") || pdu.hasTag("log")) { + worker.log(pdu.copy()); + } + + return true; + } + + @Override + public boolean prepare() { + return true; + } + + @Override + public void stop() { + // No action needed. + } + + public void setWorker(LoggerWorker worker) { + this.worker = worker; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptorModule.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptorModule.java new file mode 100644 index 0000000..7aed134 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptorModule.java @@ -0,0 +1,57 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.logger; + +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.interceptor.worker.Interceptor; +import com.warxim.petep.persistence.Configurable; + +/** Logger interceptor module. */ +public final class LoggerInterceptorModule extends InterceptorModule + implements Configurable { + private LoggerConfig config; + + /** Logger interceptor module constructor. */ + public LoggerInterceptorModule( + LoggerInterceptorModuleFactory factory, + String code, + String name, + String description, + boolean enabled) { + super(factory, code, name, description, enabled); + } + + @Override + public LoggerConfig saveConfig() { + return config; + } + + @Override + public void loadConfig(LoggerConfig config) { + this.config = config; + } + + @Override + public Interceptor createInterceptor(int id, PetepHelper helper) { + return new LoggerInterceptor(id, this, helper); + } + + public LoggerConfig getConfig() { + return config; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptorModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptorModuleFactory.java new file mode 100644 index 0000000..ab04a4e --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerInterceptorModuleFactory.java @@ -0,0 +1,57 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.logger; + +import java.io.IOException; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.persistence.Configurator; + +/** Logger interceptor module factory. */ +public final class LoggerInterceptorModuleFactory extends InterceptorModuleFactory + implements Configurator { + /** Logger interceptor module factory constructor. */ + public LoggerInterceptorModuleFactory(Extension extension) { + super(extension); + } + + @Override + public String getName() { + return "Logger"; + } + + @Override + public String getCode() { + return "logger"; + } + + @Override + public InterceptorModule createModule( + String code, + String name, + String description, + boolean enabled) { + return new LoggerInterceptorModule(this, code, name, description, enabled); + } + + @Override + public ConfigPane createConfigPane() throws IOException { + return new LoggerConfigurator(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/logger/LoggerWorker.java b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerWorker.java new file mode 100644 index 0000000..42ca8ba --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/logger/LoggerWorker.java @@ -0,0 +1,160 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.logger; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.common.Constant; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.core.pdu.PduQueue; +import com.warxim.petep.proxy.serizalization.ProxySerializer; +import com.warxim.petep.proxy.worker.Proxy; +import com.warxim.petep.util.FileUtils; +import com.warxim.petep.util.PduUtils; + +/** Logger worker. */ +public final class LoggerWorker implements Runnable { + private static final int RECORDS_PER_FILE = 10000; + private final PduQueue queue; + private final String path; + private final SimpleDateFormat formatter; + + /** Logger worker constructor. */ + public LoggerWorker(String path) { + this.queue = new PduQueue(); + this.path = path; + this.formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); + } + + public void log(PDU pdu) { + queue.add(pdu); + } + + @Override + public void run() { + Logger.getGlobal().info("Logger for path '" + path + "' started."); + + Path source = Paths.get(FileUtils.getProjectFileAbsolutePath(path)); + + while (log()) { + // Create backup + try { + if (source.getFileName().toString().contains(".")) { + // [FILE_NAME].backup_[timestamp].[EXTENSION] + Files.move(source, + source.resolveSibling(source.getFileName() + .toString() + .replaceFirst("(.+)[.]([^.]+)$", + "$1.backup_" + (System.currentTimeMillis() / 100) + ".$2"))); + } else { + // [FILE_NAME]_backup_[timestamp] + Files.move(source, source.resolveSibling( + source.getFileName() + "_backup_" + (System.currentTimeMillis() / 100))); + } + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Logger encountered an exception.", e); + } + } + } + + /** Logging to file. Returns true if logging should continue. */ + private boolean log() { + try (PrintWriter writer = new PrintWriter( + new BufferedWriter(new FileWriter(FileUtils.getProjectFileAbsolutePath(path), true)))) { + PDU pdu; + + int counter = 0; + while ((pdu = queue.take()) != null) { + // Info + Proxy proxy = pdu.getProxy(); + writer.write("###############################################\r\nTime: "); + writer.write(formatter.format(new Date())); + writer.write("\r\nProxy: "); + writer.write(proxy.getModule().getCode()); + writer.write("\r\nDestination: "); + writer.write(pdu.getDestination() == PduDestination.CLIENT ? "client" : "server"); + writer.write("\r\nConnection: "); + writer.write(String.valueOf(pdu.getConnection().getId())); + + // Tags + Set tags = pdu.getTags(); + if (!tags.isEmpty()) { + writer.write("\r\nTags: "); + writer.write(PduUtils.tagsToString(tags)); + } + + // Meta data + ProxySerializer serializer = proxy.getModule().getFactory().getSerializer(); + if (serializer != null) { + Map metadata = serializer.serializePduMetadata(pdu); + + if (metadata != null && !metadata.isEmpty()) { + writer.write("\r\nMeta data:\r\n"); + for (var item : metadata.entrySet()) { + writer.write("\t"); + writer.write(item.getKey()); + writer.write(": "); + writer.write(item.getValue()); + writer.write("\r\n"); + } + } else { + writer.write("\r\n"); + } + } else { + writer.write("\r\n"); + } + + // Data + writer.write("Data [bytes]:\r\n-----------------------------\r\n"); + writer.write(PduUtils.bufferToString(pdu)); + writer.write( + "\r\n-----------------------------\r\nData [string]:\r\n-----------------------------\r\n"); + writer.write(new String(pdu.getBuffer(), 0, pdu.getSize(), Constant.DEFAULT_CHARSET)); + writer.write("\r\n-----------------------------\r\n\r\n"); + + // Create backup. + if (++counter == RECORDS_PER_FILE) { + return true; + } + + // Save the buffered data if there are no PDUs waiting in the queue. + if (queue.isEmpty()) { + writer.flush(); + } + } + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Logger stopped with exception.", e); + } catch (InterruptedException e) { + // Interrupted. + Thread.currentThread().interrupt(); + } + + return false; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierApi.java b/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierApi.java new file mode 100644 index 0000000..b132b26 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierApi.java @@ -0,0 +1,27 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier; + +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory; + +@PetepAPI +/** Interface for registration of modifier factories. */ +public interface ModifierApi { + /** Registers modifier factories. */ + boolean registerModifierFactory(ModifierFactory factory); +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierExtension.java b/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierExtension.java new file mode 100644 index 0000000..d766062 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierExtension.java @@ -0,0 +1,172 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupsGuiFactory; +import com.warxim.petep.extension.internal.modifier.config.ModifierConfig; +import com.warxim.petep.extension.internal.modifier.config.ModifyRuleConfig; +import com.warxim.petep.extension.internal.modifier.config.ModifyRuleGroupConfig; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactoryManager; +import com.warxim.petep.extension.internal.modifier.factory.internal.replace.ReplacerFactory; +import com.warxim.petep.extension.internal.modifier.gui.ModifierController; +import com.warxim.petep.extension.internal.modifier.intercept.ModifierInterceptorModuleFactory; +import com.warxim.petep.extension.internal.modifier.rule.ModifyRule; +import com.warxim.petep.extension.internal.modifier.rule.ModifyRuleGroupManager; +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.helper.GuiHelper; +import com.warxim.petep.persistence.Storable; + +public final class ModifierExtension extends Extension + implements Storable, ModifierApi { + private final ModifierFactoryManager moduleManager; + private final ModifyRuleGroupManager groupManager; + + private ExtensionHelper helper; + private ModifierConfig config; + + public ModifierExtension(String path) { + super(path); + + moduleManager = new ModifierFactoryManager(); + groupManager = new ModifyRuleGroupManager(); + } + + @Override + public void init(ExtensionHelper helper) { + this.helper = helper; + + moduleManager.registerFactory(new ReplacerFactory()); + + initGroupManager(); + + helper.registerInterceptorModuleFactory(new ModifierInterceptorModuleFactory(this)); + } + + @Override + public void initGui(GuiHelper helper) { + try { + helper.registerTab("Modifier", RuleGroupsGuiFactory + .createRoleGroupsNode(new ModifierController(groupManager, this.helper, moduleManager))); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not load modifier tab!", e); + } + + helper.registerGuide(new ModifierGuide()); + } + + @Override + public String getCode() { + return "modifier"; + } + + @Override + public String getName() { + return "Modifier"; + } + + @Override + public String getDescription() { + return "Process PDUs using different algorithms for replacing etc."; + } + + @Override + public String getVersion() { + return "0.5"; + } + + public ModifyRuleGroupManager getRuleGroupManager() { + return groupManager; + } + + @Override + public ModifierConfig saveStore() { + List groups = new ArrayList<>(groupManager.size()); + + for (RuleGroup group : groupManager.getList()) { + List rules = new ArrayList<>(group.size()); + + for (ModifyRule rule : group.getRules()) { + rules.add(new ModifyRuleConfig(rule.getName(), rule.getDescription(), rule.isEnabled(), + rule.getTag(), rule.getModifier().getFactory().getCode(), + rule.getModifier().getData())); + } + + groups.add(new ModifyRuleGroupConfig(group.getCode(), group.getName(), rules)); + } + + return new ModifierConfig(groups); + } + + @Override + public void loadStore(ModifierConfig store) { + config = store; + } + + private void initGroupManager() { + Gson gson = new GsonBuilder().create(); + + if (config != null) { + // Process groups. + for (ModifyRuleGroupConfig groupConfig : config.getGroups()) { + RuleGroup group = new RuleGroup<>(groupConfig.getCode(), groupConfig.getName()); + + // Process rules. + for (ModifyRuleConfig ruleConfig : groupConfig.getRules()) { + ModifierFactory module = moduleManager.getFactory(ruleConfig.getFactoryCode()); + + // No module found. + if (module == null) { + Logger.getGlobal() + .severe("Could not load module " + ruleConfig.getFactoryCode() + " - rule " + + ruleConfig.getName() + " not loaded!"); + continue; + } + + // Add rule. + try { + group.addRule(new ModifyRule(ruleConfig.getName(), ruleConfig.getDescription(), + ruleConfig.isEnabled(), ruleConfig.getTag(), module + .createModifier(gson.fromJson(ruleConfig.getData(), module.getConfigType())))); + } catch (JsonParseException e) { + Logger.getGlobal() + .log(Level.SEVERE, "Could not load rule " + ruleConfig.getName() + "!", e); + } + } + + groupManager.add(group); + } + + config = null; + } + } + + @Override + public boolean registerModifierFactory(ModifierFactory module) { + return moduleManager.registerFactory(module); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierGuide.java b/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierGuide.java new file mode 100644 index 0000000..a22a5a0 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/ModifierGuide.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier; + +import com.warxim.petep.gui.guide.Guide; + +/** Modifier guide. */ +public final class ModifierGuide extends Guide { + @Override + public String getTitle() { + return "Modifier"; + } + + @Override + public String getHtml() { + return loadHtmlResource("/html/guide/internal/ModifierGuide.html"); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifierConfig.java b/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifierConfig.java new file mode 100644 index 0000000..a595eaa --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifierConfig.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.config; + +import java.util.List; + +public final class ModifierConfig { + private final List groups; + + /** Modifier configuration constructor. */ + public ModifierConfig(List groups) { + this.groups = groups; + } + + public List getGroups() { + return groups; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifyRuleConfig.java b/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifyRuleConfig.java new file mode 100644 index 0000000..a89c323 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifyRuleConfig.java @@ -0,0 +1,72 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.config; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.warxim.petep.extension.internal.modifier.factory.ModifierData; + +/** Configuration of modify rule. */ +public final class ModifyRuleConfig { + private final String name; + private final String description; + private final boolean enabled; + private final String tag; + private final String factoryCode; + private final JsonElement data; + + /** Modify rule config constructor. */ + public ModifyRuleConfig( + String name, + String description, + boolean enabled, + String tag, + String factoryCode, + ModifierData data) { + this.name = name; + this.description = description; + this.enabled = enabled; + this.tag = tag; + this.factoryCode = factoryCode; + + this.data = new GsonBuilder().setPrettyPrinting().create().toJsonTree(data); + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public boolean isEnabled() { + return enabled; + } + + public String getTag() { + return tag; + } + + public String getFactoryCode() { + return factoryCode; + } + + public JsonElement getData() { + return data; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifyRuleGroupConfig.java b/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifyRuleGroupConfig.java new file mode 100644 index 0000000..231093b --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/config/ModifyRuleGroupConfig.java @@ -0,0 +1,45 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.config; + +import java.util.List; + +/** Configuration of group of modify rules. */ +public final class ModifyRuleGroupConfig { + private final String code; + private final String name; + private final List rules; + + /** Modify rule group config. */ + public ModifyRuleGroupConfig(String code, String name, List rules) { + this.code = code; + this.name = name; + this.rules = rules; + } + + public String getCode() { + return code; + } + + public String getName() { + return name; + } + + public List getRules() { + return rules; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/Modifier.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/Modifier.java new file mode 100644 index 0000000..669c934 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/Modifier.java @@ -0,0 +1,52 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.factory; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.PetepAPI; + +@PetepAPI +public abstract class Modifier { + protected final ModifierFactory factory; + + protected ModifierData data; + + public Modifier(ModifierFactory factory, ModifierData data) { + this.factory = factory; + this.data = data; + } + + public ModifierFactory getFactory() { + return factory; + } + + public ModifierData getData() { + return data; + } + + /** + * Processes PDU in the modifier. + * + * @return FALSE if PDU should be dropped. + */ + public abstract boolean process(PDU pdu); + + @Override + public String toString() { + return factory.getName(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierConfigurator.java new file mode 100644 index 0000000..b5753d3 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierConfigurator.java @@ -0,0 +1,28 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.factory; + +import java.io.IOException; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.gui.component.ConfigPane; + +@PetepAPI +public abstract class ModifierConfigurator extends ConfigPane { + public ModifierConfigurator(String template) throws IOException { + super(template); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierData.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierData.java new file mode 100644 index 0000000..4c58869 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierData.java @@ -0,0 +1,24 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.factory; + +import com.warxim.petep.extension.PetepAPI; + +/** Processor data. */ +@PetepAPI +public class ModifierData { +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierFactory.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierFactory.java new file mode 100644 index 0000000..d291317 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierFactory.java @@ -0,0 +1,45 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.factory; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.PetepAPI; + +/** Modifier factory. */ +@PetepAPI +public abstract class ModifierFactory { + /** Returns factory code (for configuration purposes). */ + public abstract String getCode(); + + /** Returns factory name (visible for user). */ + public abstract String getName(); + + /** Creates modifier using given data. */ + public abstract Modifier createModifier(ModifierData data); + + /** Creates config pane for modifier data. */ + public abstract ModifierConfigurator createConfigPane() throws IOException; + + /** Returns type of configuration, so it can be deserialized from JSON configuration. */ + public abstract Type getConfigType(); + + @Override + public String toString() { + return getName(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierFactoryManager.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierFactoryManager.java new file mode 100644 index 0000000..ab9455e --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/ModifierFactoryManager.java @@ -0,0 +1,44 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.factory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** Modifier factory manager. */ +public final class ModifierFactoryManager { + private final Map factories; + + /** MOdifier factory manager constructor. */ + public ModifierFactoryManager() { + factories = new ConcurrentHashMap<>(); + } + + public boolean registerFactory(ModifierFactory factory) { + return factories.putIfAbsent(factory.getCode(), factory) == null; + } + + public ModifierFactory getFactory(String code) { + return factories.get(code); + } + + public List getFactories() { + return new ArrayList<>(factories.values()); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/Replacer.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/Replacer.java new file mode 100644 index 0000000..0420605 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/Replacer.java @@ -0,0 +1,43 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.factory.internal.replace; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.modifier.factory.Modifier; +import com.warxim.petep.extension.internal.modifier.factory.ModifierData; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory; +import com.warxim.petep.util.PduUtils; + +public final class Replacer extends Modifier { + public Replacer(ModifierFactory factory, ModifierData data) { + super(factory, data); + } + + @Override + public boolean process(PDU pdu) { + ReplacerData rule = (ReplacerData) data; + + // run replace + if (rule.getOccurrence() == -1) { + PduUtils.replace(pdu, rule.getWhat(), rule.getWith()); + } else { + PduUtils.replace(pdu, rule.getWhat(), rule.getWith(), rule.getOccurrence()); + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerConfigurator.java new file mode 100644 index 0000000..8f64f69 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerConfigurator.java @@ -0,0 +1,70 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.factory.internal.replace; + +import java.io.IOException; +import com.warxim.petep.extension.internal.modifier.factory.ModifierConfigurator; +import com.warxim.petep.extension.internal.modifier.factory.ModifierData; +import com.warxim.petep.gui.control.BytesEditor; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.fxml.FXML; +import javafx.scene.control.TextField; + +public final class ReplacerConfigurator extends ModifierConfigurator { + @FXML + private TextField occurrenceInput; + + @FXML + private BytesEditor whatInput; + + @FXML + private BytesEditor withInput; + + public ReplacerConfigurator() throws IOException { + super("/fxml/extension/internal/modifier/factory/Replace.fxml"); + + occurrenceInput.setText("-1"); + } + + @Override + public ModifierData getConfig() { + return new ReplacerData(Integer.parseInt(occurrenceInput.getText()), whatInput.getBytes(), + withInput.getBytes()); + } + + @Override + public void setConfig(ModifierData config) { + occurrenceInput.setText(String.valueOf(((ReplacerData) config).getOccurrence())); + whatInput.setBytes(((ReplacerData) config).getWhat()); + withInput.setBytes(((ReplacerData) config).getWith()); + } + + @Override + public boolean isValid() { + if (occurrenceInput.getText().length() == 0) { + Dialogs.createErrorDialog("Occurrence required", "You have to enter occurrence."); + return false; + } + + if (whatInput.getBytes().length == 0) { + Dialogs.createErrorDialog("What required", "You have to enter what."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerData.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerData.java new file mode 100644 index 0000000..71ae8f2 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerData.java @@ -0,0 +1,45 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.factory.internal.replace; + +import com.warxim.petep.extension.internal.modifier.factory.ModifierData; + +public final class ReplacerData extends ModifierData { + /** 0 = replace all, 1 .. n = replace n-th occurrence. */ + private final int occurrence; + + private final byte[] what; + private final byte[] with; + + public ReplacerData(int occurrence, byte[] what, byte[] with) { + this.occurrence = occurrence; + this.what = what; + this.with = with; + } + + public int getOccurrence() { + return occurrence; + } + + public byte[] getWhat() { + return what; + } + + public byte[] getWith() { + return with; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerFactory.java b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerFactory.java new file mode 100644 index 0000000..dcd8216 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/factory/internal/replace/ReplacerFactory.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.factory.internal.replace; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.internal.modifier.factory.Modifier; +import com.warxim.petep.extension.internal.modifier.factory.ModifierConfigurator; +import com.warxim.petep.extension.internal.modifier.factory.ModifierData; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory; + +public final class ReplacerFactory extends ModifierFactory { + @Override + public String getCode() { + return "replace"; + } + + @Override + public String getName() { + return "Replace"; + } + + @Override + public Type getConfigType() { + return ReplacerData.class; + } + + @Override + public Modifier createModifier(ModifierData data) { + return new Replacer(this, data); + } + + @Override + public ModifierConfigurator createConfigPane() throws IOException { + return new ReplacerConfigurator(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/gui/ModifierController.java b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/ModifierController.java new file mode 100644 index 0000000..28eb834 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/ModifierController.java @@ -0,0 +1,61 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.gui; + +import java.io.IOException; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupController; +import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupsController; +import com.warxim.petep.extension.internal.common.rule_group.intercept.RuleInterceptorModule; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactoryManager; +import com.warxim.petep.extension.internal.modifier.intercept.ModifierInterceptorModule; +import com.warxim.petep.extension.internal.modifier.rule.ModifyRule; +import com.warxim.petep.extension.internal.modifier.rule.ModifyRuleGroupManager; +import com.warxim.petep.helper.ExtensionHelper; +import javafx.fxml.FXMLLoader; +import javafx.scene.Node; +import javafx.util.Pair; + +public final class ModifierController extends RuleGroupsController { + private final ModifierFactoryManager factoryManager; + + public ModifierController( + ModifyRuleGroupManager groupManager, + ExtensionHelper extensionHelper, + ModifierFactoryManager factoryManager) { + super("Modifier", groupManager, extensionHelper); + this.factoryManager = factoryManager; + } + + @Override + protected Class> getInterceptorModuleClass() { + return ModifierInterceptorModule.class; + } + + @Override + protected Pair> createGroupTabNode( + RuleGroup group) throws IOException { + FXMLLoader fxmlLoader = new FXMLLoader( + getClass().getResource("/fxml/extension/internal/modifier/ModifyRuleGroup.fxml")); + + ModifyGroupController controller = new ModifyGroupController(group, factoryManager); + + fxmlLoader.setController(controller); + + return new Pair<>(fxmlLoader.load(), controller); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/gui/ModifyGroupController.java b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/ModifyGroupController.java new file mode 100644 index 0000000..c1d5d10 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/ModifyGroupController.java @@ -0,0 +1,168 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.gui; + +import java.io.IOException; +import java.net.URL; +import java.util.Optional; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupController; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactoryManager; +import com.warxim.petep.extension.internal.modifier.gui.rule.EditModifyRuleDialog; +import com.warxim.petep.extension.internal.modifier.gui.rule.NewProcessRuleDialog; +import com.warxim.petep.extension.internal.modifier.rule.ModifyRule; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.collections.FXCollections; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; + +/** Modify group controller. */ +public final class ModifyGroupController extends RuleGroupController + implements Initializable { + private final ModifierFactoryManager factoryManager; + + @FXML + private TableView table; + + @FXML + private TableColumn nameColumn; + + @FXML + private TableColumn tagColumn; + + @FXML + private TableColumn factoryColumn; + + @FXML + private TableColumn enabledColumn; + + /** Modify group controller constructor. */ + public ModifyGroupController(RuleGroup group, ModifierFactoryManager factoryManager) { + super(group); + this.factoryManager = factoryManager; + } + + @Override + public void initialize(URL location, ResourceBundle resources) { + nameColumn.setCellValueFactory(new PropertyValueFactory<>("name")); + tagColumn.setCellValueFactory(new PropertyValueFactory<>("tag")); + factoryColumn.setCellValueFactory(new PropertyValueFactory<>("modifier")); + enabledColumn.setCellValueFactory(new PropertyValueFactory<>("enabled")); + + table.setItems(FXCollections.observableList(group.getRules())); + } + + @FXML + private void onNewButtonClick(ActionEvent event) { + try { + NewProcessRuleDialog dialog = new NewProcessRuleDialog(factoryManager); + + Optional data = dialog.showAndWait(); + + if (!data.isPresent() || data.get() == null) { + return; + } + + group.addRule(data.get()); + + refresh(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during openning of modify rule dialog", e); + } + } + + @FXML + private void onEditButtonClick(ActionEvent event) { + ModifyRule rule = table.getSelectionModel().getSelectedItem(); + + if (rule == null) { + return; + } + + try { + EditModifyRuleDialog dialog = new EditModifyRuleDialog(factoryManager, rule); + + Optional data = dialog.showAndWait(); + + if (!data.isPresent() || data.get() == null) { + return; + } + + group.replace(rule, data.get()); + + refresh(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during openning of modify rule dialog", e); + } + } + + @FXML + private void onRemoveButtonClick(ActionEvent event) { + ModifyRule rule = table.getSelectionModel().getSelectedItem(); + + if (rule == null) { + return; + } + + // Does user really want to remove rule? + if (!Dialogs.createYesOrNoDialog("Are you sure?", + "Do you really want to remove rule '" + rule.getName() + "'?")) { + return; + } + + group.removeRule(rule); + + refresh(); + } + + @FXML + private void onMoveUpButtonClick(ActionEvent event) { + int index = table.getSelectionModel().getSelectedIndex(); + + if (index <= 0) { + return; + } + + group.swapRules(index, index - 1); + + refresh(); + } + + @FXML + private void onMoveDownButtonClick(ActionEvent event) { + int index = table.getSelectionModel().getSelectedIndex(); + + if (index == -1 || index == group.ruleCount() - 1) { + return; + } + + group.swapRules(index, index + 1); + + refresh(); + } + + private void refresh() { + table.setItems(FXCollections.observableList(group.getRules())); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/EditModifyRuleDialog.java b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/EditModifyRuleDialog.java new file mode 100644 index 0000000..7722ffc --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/EditModifyRuleDialog.java @@ -0,0 +1,57 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.gui.rule; + +import java.io.IOException; +import com.warxim.petep.extension.internal.modifier.factory.Modifier; +import com.warxim.petep.extension.internal.modifier.factory.ModifierData; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactoryManager; +import com.warxim.petep.extension.internal.modifier.rule.ModifyRule; +import com.warxim.petep.gui.component.ConfigPane; + +/** Edit modify rule dialog. */ +public final class EditModifyRuleDialog extends ModifyRuleDialog { + /** Edit modify rule dialog constructor. */ + public EditModifyRuleDialog(ModifierFactoryManager factoryManager, ModifyRule rule) + throws IOException { + super("Edit modify rule", "Save", factoryManager); + + nameInput.setText(rule.getName()); + descriptionInput.setText(rule.getDescription()); + tagInput.setText(rule.getTag()); + enabledInput.setSelected(rule.isEnabled()); + + Modifier processor = rule.getModifier(); + factoryInput.getSelectionModel().select(processor.getFactory()); + + // Load config pane. + ConfigPane pane = createFactoryPane(); + if (pane == null) { + return; + } + setFactoryPane(pane); + + // Get configuration from instance. + ModifierData data = processor.getData(); + if (data == null) { + return; + } + + // Set config to pane. + pane.setConfig(data); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/ModifyRuleDialog.java b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/ModifyRuleDialog.java new file mode 100644 index 0000000..ae271f6 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/ModifyRuleDialog.java @@ -0,0 +1,160 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.gui.rule; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.extension.internal.modifier.factory.ModifierData; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactory; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactoryManager; +import com.warxim.petep.extension.internal.modifier.rule.ModifyRule; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.gui.dialog.SimpleInputDialog; +import javafx.collections.FXCollections; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ComboBox; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; +import javafx.scene.layout.AnchorPane; +import javafx.util.StringConverter; + +/** Modify rule dialog. */ +public abstract class ModifyRuleDialog extends SimpleInputDialog { + @FXML + protected ComboBox factoryInput; + + @FXML + protected AnchorPane factoryPane; + + @FXML + protected TextField nameInput; + + @FXML + protected TextArea descriptionInput; + + @FXML + protected TextField tagInput; + + @FXML + protected CheckBox enabledInput; + + /** Modify rule dialog constructor. */ + public ModifyRuleDialog(String title, String okText, ModifierFactoryManager factoryManager) + throws IOException { + super("/fxml/extension/internal/modifier/ModifyRuleDialog.fxml", title, okText); + + enabledInput.setSelected(true); + + // Show factory name as factory input text. + factoryInput.setConverter(new StringConverter() { + @Override + public String toString(ModifierFactory factory) { + if (factory == null) { + return ""; + } + return factory.getName(); + } + + @Override + public ModifierFactory fromString(String str) { + return null; + } + }); + + factoryInput.setItems(FXCollections.observableArrayList(factoryManager.getFactories())); + } + + protected final void setFactoryPane(ConfigPane pane) { + if (pane == null) { + // Clear factory pane if config pane does not exist. + factoryPane.getChildren().clear(); + return; + } + + AnchorPane.setLeftAnchor(pane, 0D); + AnchorPane.setRightAnchor(pane, 0D); + + // Add config pane to factory pane. + factoryPane.getChildren().setAll(pane); + } + + protected final ConfigPane createFactoryPane() { + ModifierFactory factory = factoryInput.getSelectionModel().getSelectedItem(); + + if (factory == null) { + return null; + } + + try { + return factory.createConfigPane(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not load factory config pane.", e); + } + + return null; + } + + @FXML + private final void onFactoryChange(ActionEvent event) { + setFactoryPane(createFactoryPane()); + } + + @SuppressWarnings("unchecked") + @Override + protected final boolean isValid() { + if (nameInput.getText().isEmpty()) { + Dialogs.createErrorDialog("Name required", "You have to enter name."); + return false; + } + + // Validate tag. + if (!tagInput.getText().isEmpty() && !tagInput.getText().matches("^[a-zA-Z0-9-_.]+$")) { + Dialogs.createErrorDialog("Tag invalid", + "You have entered invalid tag (allowed characters are A-Za-z0-9-_.)."); + return false; + } + + // Validate factory + ModifierFactory factory = factoryInput.getSelectionModel().getSelectedItem(); + if (factory == null) { + Dialogs.createErrorDialog("Factory required", "You have to select factory."); + return false; + } + + // Validate configuration pane + if (!factoryPane.getChildren().isEmpty() + && !((ConfigPane) factoryPane.getChildren().get(0)).isValid()) { + return false; + } + + return true; + } + + @SuppressWarnings("unchecked") + @Override + protected final ModifyRule obtainResult() { + ModifierFactory factory = factoryInput.getSelectionModel().getSelectedItem(); + + return new ModifyRule(nameInput.getText(), descriptionInput.getText(), + enabledInput.isSelected(), tagInput.getText(), factory.createModifier( + ((ConfigPane) factoryPane.getChildren().get(0)).getConfig())); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/NewProcessRuleDialog.java b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/NewProcessRuleDialog.java new file mode 100644 index 0000000..8730961 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/gui/rule/NewProcessRuleDialog.java @@ -0,0 +1,28 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.gui.rule; + +import java.io.IOException; +import com.warxim.petep.extension.internal.modifier.factory.ModifierFactoryManager; + +/** New modify rule dialog. */ +public final class NewProcessRuleDialog extends ModifyRuleDialog { + /** New modify rule dialog constructor. */ + public NewProcessRuleDialog(ModifierFactoryManager factoryManager) throws IOException { + super("New modify rule", "Create", factoryManager); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptor.java b/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptor.java new file mode 100644 index 0000000..f982e1f --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptor.java @@ -0,0 +1,56 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.intercept; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.modifier.rule.ModifyRule; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.worker.Interceptor; + +/** Modifier interceptor. */ +public final class ModifierInterceptor extends Interceptor { + private final RuleGroup group; + + /** Modifier interceptor constructor. */ + public ModifierInterceptor(int id, ModifierInterceptorModule module, PetepHelper helper) { + super(id, module, helper); + + this.group = module.getRuleGroup(); + } + + @Override + public boolean prepare() { + return true; + } + + @Override + public boolean intercept(PDU pdu) { + for (ModifyRule rule : group.getRules()) { + if (!rule.process(pdu)) { + return false; + } + } + + return true; + } + + @Override + public void stop() { + // No action needed. + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptorModule.java b/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptorModule.java new file mode 100644 index 0000000..e800f59 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptorModule.java @@ -0,0 +1,64 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.intercept; + +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.config.RuleInterceptorConfig; +import com.warxim.petep.extension.internal.common.rule_group.intercept.RuleInterceptorModule; +import com.warxim.petep.extension.internal.modifier.ModifierExtension; +import com.warxim.petep.extension.internal.modifier.rule.ModifyRule; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.worker.Interceptor; +import com.warxim.petep.persistence.Configurable; + +/** Modifier interceptor module. */ +public final class ModifierInterceptorModule extends RuleInterceptorModule + implements Configurable { + private RuleGroup group; + + /** Modifier interceptor module constructor. */ + public ModifierInterceptorModule( + InterceptorModuleFactory factory, + String code, + String name, + String description, + boolean enabled) { + super(factory, code, name, description, enabled); + } + + @Override + public Interceptor createInterceptor(int id, PetepHelper helper) { + return new ModifierInterceptor(id, this, helper); + } + + @Override + public RuleInterceptorConfig saveConfig() { + return new RuleInterceptorConfig(group.getCode()); + } + + @Override + public void loadConfig(RuleInterceptorConfig config) { + group = ((ModifierExtension) factory.getExtension()).getRuleGroupManager() + .get(config.getRuleGroupCode()); + } + + @Override + public RuleGroup getRuleGroup() { + return group; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptorModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptorModuleFactory.java new file mode 100644 index 0000000..b4caec4 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/intercept/ModifierInterceptorModuleFactory.java @@ -0,0 +1,60 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.intercept; + +import java.io.IOException; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.internal.common.rule_group.config.RuleInterceptorConfig; +import com.warxim.petep.extension.internal.common.rule_group.gui.RuleInterceptorConfigurator; +import com.warxim.petep.extension.internal.modifier.ModifierExtension; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.persistence.Configurator; + +/** Modifier interceptor module. */ +public final class ModifierInterceptorModuleFactory extends InterceptorModuleFactory + implements Configurator { + /** Modifier interceptor module constructor. */ + public ModifierInterceptorModuleFactory(Extension extension) { + super(extension); + } + + @Override + public String getCode() { + return "modifier"; + } + + @Override + public String getName() { + return "Modifier"; + } + + @Override + public InterceptorModule createModule( + String code, + String name, + String description, + boolean enabled) { + return new ModifierInterceptorModule(this, code, name, description, enabled); + } + + @Override + public ConfigPane createConfigPane() throws IOException { + return new RuleInterceptorConfigurator<>(((ModifierExtension) extension).getRuleGroupManager()); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/rule/ModifyRule.java b/src/main/java/com/warxim/petep/extension/internal/modifier/rule/ModifyRule.java new file mode 100644 index 0000000..9549f8a --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/rule/ModifyRule.java @@ -0,0 +1,55 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.rule; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.common.rule_group.Rule; +import com.warxim.petep.extension.internal.modifier.factory.Modifier; + +/** Modify rule. */ +public final class ModifyRule extends Rule { + private final String tag; + private final Modifier modifier; + + /** Modify rule constructor. */ + public ModifyRule( + String name, + String description, + boolean enabled, + String tag, + Modifier modifier) { + super(name, description, enabled); + this.tag = tag; + this.modifier = modifier; + } + + public String getTag() { + return tag; + } + + public Modifier getModifier() { + return modifier; + } + + public boolean process(PDU pdu) { + if ((!enabled) || (!tag.isEmpty() && !pdu.hasTag(tag))) { + return true; + } + + return modifier.process(pdu); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/modifier/rule/ModifyRuleGroupManager.java b/src/main/java/com/warxim/petep/extension/internal/modifier/rule/ModifyRuleGroupManager.java new file mode 100644 index 0000000..03d1a04 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/modifier/rule/ModifyRuleGroupManager.java @@ -0,0 +1,28 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.modifier.rule; + +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager; + +/** Modify rule group manager. */ +public final class ModifyRuleGroupManager extends RuleGroupManager> { + /** Modify rule group manager constructor. */ + public ModifyRuleGroupManager() { + super(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerApi.java b/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerApi.java new file mode 100644 index 0000000..c898cd5 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerApi.java @@ -0,0 +1,27 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger; + +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +@PetepAPI +/** Interface for registration of tag subrule factories. */ +public interface TaggerApi { + /** Registers tag subrule factory. */ + boolean registerSubruleFactory(TagSubruleFactory factory); +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerExtension.java b/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerExtension.java new file mode 100644 index 0000000..8b92266 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerExtension.java @@ -0,0 +1,228 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.warxim.booleanexpressioninterpreter.InvalidExpressionException; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupsGuiFactory; +import com.warxim.petep.extension.internal.tagger.config.TagRuleConfig; +import com.warxim.petep.extension.internal.tagger.config.TagRuleGroupConfig; +import com.warxim.petep.extension.internal.tagger.config.TagSubruleConfig; +import com.warxim.petep.extension.internal.tagger.config.TaggerConfig; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager; +import com.warxim.petep.extension.internal.tagger.factory.internal.contains.ContainsSubruleFactory; +import com.warxim.petep.extension.internal.tagger.factory.internal.destination.DestinationSubruleFactory; +import com.warxim.petep.extension.internal.tagger.factory.internal.ends_with.EndsWithSubruleFactory; +import com.warxim.petep.extension.internal.tagger.factory.internal.has_tag.HasTagSubruleFactory; +import com.warxim.petep.extension.internal.tagger.factory.internal.proxy.ProxySubruleFactory; +import com.warxim.petep.extension.internal.tagger.factory.internal.size.SizeSubruleFactory; +import com.warxim.petep.extension.internal.tagger.factory.internal.starts_with.StartsWithSubruleFactory; +import com.warxim.petep.extension.internal.tagger.gui.TaggerController; +import com.warxim.petep.extension.internal.tagger.intercept.TagInterceptorModuleFactory; +import com.warxim.petep.extension.internal.tagger.rule.TagRule; +import com.warxim.petep.extension.internal.tagger.rule.TagRuleGroupManager; +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.helper.GuiHelper; +import com.warxim.petep.persistence.Storable; + +/** Tagger extension. */ +public final class TaggerExtension extends Extension + implements Storable, TaggerApi { + private ExtensionHelper helper; + + private final TagRuleGroupManager groupManager; + private final TagSubruleFactoryManager factoryManager; + + private TaggerConfig config; + + /** Tagger extension constructor. */ + public TaggerExtension(String path) { + super(path); + + factoryManager = new TagSubruleFactoryManager(); + groupManager = new TagRuleGroupManager(); + } + + @Override + public void init(ExtensionHelper helper) { + this.helper = helper; + + registerInternalModules(); + + initGroupManager(); + + helper.registerInterceptorModuleFactory(new TagInterceptorModuleFactory(this)); + } + + @Override + public void initGui(GuiHelper helper) { + try { + helper.registerTab("Tagger", RuleGroupsGuiFactory + .createRoleGroupsNode(new TaggerController(groupManager, this.helper, factoryManager))); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not load replacer tab!", e); + } + + helper.registerGuide(new TaggerGuide()); + } + + @Override + public String getCode() { + return "tagger"; + } + + @Override + public String getName() { + return "Tagger extension"; + } + + @Override + public String getDescription() { + return "Simple tagger extension."; + } + + @Override + public String getVersion() { + return "0.9"; + } + + @Override + public TaggerConfig saveStore() { + List groups = new ArrayList<>(groupManager.size()); + + for (RuleGroup group : groupManager.getList()) { + List rules = new ArrayList<>(group.size()); + + for (TagRule rule : group.getRules()) { + List subrules = new ArrayList<>(rule.getSubrules().size()); + + for (TagSubrule subrule : rule.getSubrules()) { + subrules.add(new TagSubruleConfig(subrule.getFactory().getCode(), subrule.getData())); + } + + rules.add(new TagRuleConfig(rule.getName(), rule.getDescription(), rule.isEnabled(), + rule.getTag(), subrules, rule.getExpressionString())); + } + groups.add(new TagRuleGroupConfig(group.getCode(), group.getName(), rules)); + } + + return new TaggerConfig(groups); + } + + @Override + public void loadStore(TaggerConfig store) { + config = store; + } + + private void registerInternalModules() { + registerSubruleFactory(new ContainsSubruleFactory()); + registerSubruleFactory(new StartsWithSubruleFactory()); + registerSubruleFactory(new EndsWithSubruleFactory()); + registerSubruleFactory(new HasTagSubruleFactory()); + registerSubruleFactory(new SizeSubruleFactory()); + registerSubruleFactory(new DestinationSubruleFactory()); + registerSubruleFactory(new ProxySubruleFactory(helper)); + } + + private void initGroupManager() { + Gson gson = new GsonBuilder().create(); + + if (config != null) { + // Process groups. + for (TagRuleGroupConfig groupConfig : config.getGroups()) { + RuleGroup group = new RuleGroup<>(groupConfig.getCode(), groupConfig.getName()); + + // Process rules. + for (TagRuleConfig ruleConfig : groupConfig.getRules()) { + List subrules = new ArrayList<>(); + + boolean isError = false; + + // Process subrules. + for (TagSubruleConfig subruleConfig : ruleConfig.getSubrules()) { + TagSubruleFactory factory = factoryManager.getFactory(subruleConfig.getFactoryCode()); + + // No factory found. + if (factory == null) { + Logger.getGlobal() + .severe("Could not load factory " + subruleConfig.getFactoryCode() + "!"); + + isError = true; + + break; + } + + // Add subrule. + try { + subrules.add(factory + .createSubrule(gson.fromJson(subruleConfig.getData(), factory.getConfigType()))); + } catch (JsonParseException e) { + Logger.getGlobal() + .log(Level.SEVERE, "Could not load rule " + ruleConfig.getName() + "!", e); + + isError = true; + + break; + } + } + + // Skip rule. + if (isError) { + Logger.getGlobal() + .severe( + "Ignoring rule " + ruleConfig.getName() + ", because there an error occured!"); + continue; + } + + // Add rule. + try { + group.addRule(new TagRule(ruleConfig.getName(), ruleConfig.getDescription(), + ruleConfig.isEnabled(), ruleConfig.getTag(), subrules, + ruleConfig.getExpressionString())); + } catch (InvalidExpressionException e) { + Logger.getGlobal() + .log(Level.SEVERE, "Could not load rule " + ruleConfig.getName() + "!", e); + } + } + + groupManager.add(group); + } + + config = null; + } + } + + public TagRuleGroupManager getRuleGroupManager() { + return groupManager; + } + + @Override + public boolean registerSubruleFactory(TagSubruleFactory factory) { + return factoryManager.registerFactory(factory); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerGuide.java b/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerGuide.java new file mode 100644 index 0000000..578a1a7 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/TaggerGuide.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger; + +import com.warxim.petep.gui.guide.Guide; + +/** Tagger guide. */ +public final class TaggerGuide extends Guide { + @Override + public String getTitle() { + return "Tagger"; + } + + @Override + public String getHtml() { + return loadHtmlResource("/html/guide/internal/TaggerGuide.html"); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagRuleConfig.java b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagRuleConfig.java new file mode 100644 index 0000000..7a8368b --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagRuleConfig.java @@ -0,0 +1,69 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.config; + +import java.util.List; + +/** Tag rule configuration. */ +public final class TagRuleConfig { + private final String name; + private final String description; + private final boolean enabled; + private final String tag; + private final String expressionString; + private final List subrules; + + /** Tag rule configuration constructor. */ + public TagRuleConfig( + String name, + String description, + boolean enabled, + String tag, + List subrules, + String expressionString) { + this.name = name; + this.description = description; + this.enabled = enabled; + this.tag = tag; + this.subrules = subrules; + this.expressionString = expressionString; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public boolean isEnabled() { + return enabled; + } + + public String getTag() { + return tag; + } + + public List getSubrules() { + return subrules; + } + + public String getExpressionString() { + return expressionString; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagRuleGroupConfig.java b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagRuleGroupConfig.java new file mode 100644 index 0000000..f42ac0b --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagRuleGroupConfig.java @@ -0,0 +1,45 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.config; + +import java.util.List; + +/** Configuration of group of tag rules. */ +public final class TagRuleGroupConfig { + private final String code; + private final String name; + private final List rules; + + /** Tag rule group config. */ + public TagRuleGroupConfig(String code, String name, List rules) { + this.code = code; + this.name = name; + this.rules = rules; + } + + public String getCode() { + return code; + } + + public String getName() { + return name; + } + + public List getRules() { + return rules; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagSubruleConfig.java b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagSubruleConfig.java new file mode 100644 index 0000000..20f39d2 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TagSubruleConfig.java @@ -0,0 +1,41 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.config; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; + +/** Configuration of tag subrules. */ +public final class TagSubruleConfig { + private final String factoryCode; + private final JsonElement data; + + /** Tag subrule config constructor. */ + public TagSubruleConfig(String factoryCode, TagSubruleData data) { + this.factoryCode = factoryCode; + this.data = new GsonBuilder().setPrettyPrinting().create().toJsonTree(data); + } + + public String getFactoryCode() { + return factoryCode; + } + + public JsonElement getData() { + return data; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/config/TaggerConfig.java b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TaggerConfig.java new file mode 100644 index 0000000..e01d85f --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/config/TaggerConfig.java @@ -0,0 +1,33 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.config; + +import java.util.List; + +/** Tagger configuration. */ +public final class TaggerConfig { + private final List groups; + + /** Tagger configuration constructor. */ + public TaggerConfig(List groups) { + this.groups = groups; + } + + public List getGroups() { + return groups; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubrule.java new file mode 100644 index 0000000..cb48c39 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubrule.java @@ -0,0 +1,48 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.PetepAPI; + +/** Tag subrule. */ +@PetepAPI +public abstract class TagSubrule { + protected final TagSubruleFactory factory; + protected TagSubruleData data; + + /** Tag subrule constructor. */ + public TagSubrule(TagSubruleFactory factory, TagSubruleData data) { + this.factory = factory; + this.data = data; + } + + public final TagSubruleFactory getFactory() { + return factory; + } + + public final TagSubruleData getData() { + return data; + } + + public abstract boolean test(PDU pdu); + + @Override + public String toString() { + return factory.getName(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleConfigurator.java new file mode 100644 index 0000000..6833e74 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleConfigurator.java @@ -0,0 +1,28 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory; + +import java.io.IOException; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.gui.component.ConfigPane; + +@PetepAPI +public abstract class TagSubruleConfigurator extends ConfigPane { + public TagSubruleConfigurator(String template) throws IOException { + super(template); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleData.java new file mode 100644 index 0000000..ff3bed6 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleData.java @@ -0,0 +1,24 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory; + +import com.warxim.petep.extension.PetepAPI; + +/** Tag subrule data. */ +@PetepAPI +public class TagSubruleData { +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleFactory.java new file mode 100644 index 0000000..096abc2 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleFactory.java @@ -0,0 +1,45 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.PetepAPI; + +/** Tag subrule factory. */ +@PetepAPI +public abstract class TagSubruleFactory { + /** Returns factory code (for configuration purposes). */ + public abstract String getCode(); + + /** Returns factory name (visible for user). */ + public abstract String getName(); + + /** Creates subrule using given data. */ + public abstract TagSubrule createSubrule(TagSubruleData data); + + /** Creates config pane for subrule data. */ + public abstract TagSubruleConfigurator createConfigPane() throws IOException; + + /** Returns type of configuration, so it can be deserialized from JSON configuration. */ + public abstract Type getConfigType(); + + @Override + public String toString() { + return getName(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleFactoryManager.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleFactoryManager.java new file mode 100644 index 0000000..fb23c9f --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/TagSubruleFactoryManager.java @@ -0,0 +1,44 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** Tag subrule factory manager. */ +public final class TagSubruleFactoryManager { + private final Map factories; + + /** Tag subrule factory manager constructor. */ + public TagSubruleFactoryManager() { + factories = new ConcurrentHashMap<>(); + } + + public boolean registerFactory(TagSubruleFactory factory) { + return factories.putIfAbsent(factory.getCode(), factory) == null; + } + + public TagSubruleFactory getFactory(String code) { + return factories.get(code); + } + + public List getFactories() { + return new ArrayList<>(factories.values()); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsData.java new file mode 100644 index 0000000..29e8a09 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsData.java @@ -0,0 +1,43 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.contains; + +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; + +public final class ContainsData extends TagSubruleData { + private final byte[] data; + private final String charset; + private final int index; + + public ContainsData(byte[] data, String charset, int index) { + this.data = data; + this.charset = charset; + this.index = index; + } + + public byte[] getData() { + return data; + } + + public String getCharset() { + return charset; + } + + public int getIndex() { + return index; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsSubruleConfigurator.java new file mode 100644 index 0000000..cdd5452 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsSubruleConfigurator.java @@ -0,0 +1,73 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.contains; + +import java.io.IOException; +import java.nio.charset.Charset; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.gui.control.BytesEditor; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.fxml.FXML; +import javafx.scene.control.TextField; + +public final class ContainsSubruleConfigurator extends TagSubruleConfigurator { + @FXML + private BytesEditor dataInput; + @FXML + private TextField indexInput; + + public ContainsSubruleConfigurator() throws IOException { + super("/fxml/extension/internal/tagger/factory/ContainsSubrule.fxml"); + } + + @Override + public TagSubruleData getConfig() { + return new ContainsData(dataInput.getBytes(), dataInput.getCharset().name(), + Integer.parseInt(indexInput.getText())); + } + + @Override + public void setConfig(TagSubruleData config) { + dataInput.setData(((ContainsData) config).getData(), + Charset.forName(((ContainsData) config).getCharset())); + indexInput.setText(String.valueOf(((ContainsData) config).getIndex())); + } + + @Override + public boolean isValid() { + if (dataInput.getBytes().length == 0) { + Dialogs.createErrorDialog("Data required", "You have enter data."); + return false; + } + + try { + int index = Integer.parseInt(indexInput.getText()); + if (index < 0 && index != -1) { + Dialogs.createErrorDialog("Invalid index", + "Index has to be -1 or number greater or equal to 0."); + return false; + } + } catch (NumberFormatException e) { + Dialogs.createErrorDialog("Invalid index", + "Index has to be -1 or number greater or equal to 0."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsSubruleFactory.java new file mode 100644 index 0000000..aec79d8 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsSubruleFactory.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.contains; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class ContainsSubruleFactory extends TagSubruleFactory { + @Override + public String getCode() { + return "contains"; + } + + @Override + public String getName() { + return "Contains ..."; + } + + @Override + public TagSubrule createSubrule(TagSubruleData data) { + return new ContainsTagSubrule(this, data); + } + + @Override + public TagSubruleConfigurator createConfigPane() throws IOException { + return new ContainsSubruleConfigurator(); + } + + @Override + public Type getConfigType() { + return ContainsData.class; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsTagSubrule.java new file mode 100644 index 0000000..293ac5d --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/contains/ContainsTagSubrule.java @@ -0,0 +1,40 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.contains; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; +import com.warxim.petep.util.PduUtils; + +public final class ContainsTagSubrule extends TagSubrule { + public ContainsTagSubrule(TagSubruleFactory factory, TagSubruleData data) { + super(factory, data); + } + + @Override + public boolean test(PDU pdu) { + ContainsData data = (ContainsData) this.data; + + if (data.getIndex() == -1) { + return PduUtils.contains(pdu, data.getData()); + } else { + return PduUtils.containsAt(pdu, data.getData(), data.getIndex()); + } + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationData.java new file mode 100644 index 0000000..39f4a36 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationData.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.destination; + +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; + +public final class DestinationData extends TagSubruleData { + private final PduDestination destination; + + public DestinationData(PduDestination destination) { + this.destination = destination; + } + + public PduDestination getDestination() { + return destination; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationSubruleConfigurator.java new file mode 100644 index 0000000..b29cc0b --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationSubruleConfigurator.java @@ -0,0 +1,75 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.destination; + +import java.io.IOException; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.collections.FXCollections; +import javafx.fxml.FXML; +import javafx.scene.control.ComboBox; +import javafx.util.StringConverter; + +public final class DestinationSubruleConfigurator extends TagSubruleConfigurator { + @FXML + private ComboBox destinationInput; + + public DestinationSubruleConfigurator() throws IOException { + super("/fxml/extension/internal/tagger/factory/DestinationSubrule.fxml"); + + destinationInput.setConverter(new StringConverter() { + @Override + public String toString(PduDestination destination) { + if (destination == null) { + return ""; + } + + return destination == PduDestination.CLIENT ? "To client" : "To server"; + } + + @Override + public PduDestination fromString(String str) { + return null; + } + }); + + destinationInput + .setItems(FXCollections.observableArrayList(PduDestination.CLIENT, PduDestination.SERVER)); + } + + @Override + public TagSubruleData getConfig() { + return new DestinationData(destinationInput.getSelectionModel().getSelectedItem()); + } + + @Override + public void setConfig(TagSubruleData config) { + destinationInput.getSelectionModel().select(((DestinationData) config).getDestination()); + } + + @Override + public boolean isValid() { + if (destinationInput.getSelectionModel().getSelectedItem() == null) { + Dialogs.createErrorDialog("Destination required", "You have to select destination."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationSubruleFactory.java new file mode 100644 index 0000000..5a71582 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationSubruleFactory.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.destination; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class DestinationSubruleFactory extends TagSubruleFactory { + @Override + public String getCode() { + return "destination"; + } + + @Override + public String getName() { + return "Destination ..."; + } + + @Override + public TagSubrule createSubrule(TagSubruleData data) { + return new DestinationTagSubrule(this, data); + } + + @Override + public TagSubruleConfigurator createConfigPane() throws IOException { + return new DestinationSubruleConfigurator(); + } + + @Override + public Type getConfigType() { + return DestinationData.class; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationTagSubrule.java new file mode 100644 index 0000000..852232a --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/destination/DestinationTagSubrule.java @@ -0,0 +1,40 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.destination; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class DestinationTagSubrule extends TagSubrule { + public DestinationTagSubrule(TagSubruleFactory factory, TagSubruleData data) { + super(factory, data); + } + + @Override + public boolean test(PDU pdu) { + return pdu.getDestination() == ((DestinationData) data).getDestination(); + } + + @Override + public String toString() { + return "To " + (((DestinationData) data).getDestination() == PduDestination.CLIENT ? "client" + : "server"); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithData.java new file mode 100644 index 0000000..078cdb2 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithData.java @@ -0,0 +1,37 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.ends_with; + +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; + +public final class EndsWithData extends TagSubruleData { + private final byte[] data; + private final String charset; + + public EndsWithData(byte[] data, String charset) { + this.data = data; + this.charset = charset; + } + + public byte[] getData() { + return data; + } + + public String getCharset() { + return charset; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithSubruleConfigurator.java new file mode 100644 index 0000000..f83b1d8 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithSubruleConfigurator.java @@ -0,0 +1,55 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.ends_with; + +import java.io.IOException; +import java.nio.charset.Charset; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.gui.control.BytesEditor; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.fxml.FXML; + +public final class EndsWithSubruleConfigurator extends TagSubruleConfigurator { + @FXML + private BytesEditor dataInput; + + public EndsWithSubruleConfigurator() throws IOException { + super("/fxml/extension/internal/tagger/factory/EndsWithSubrule.fxml"); + } + + @Override + public TagSubruleData getConfig() { + return new EndsWithData(dataInput.getBytes(), dataInput.getCharset().name()); + } + + @Override + public void setConfig(TagSubruleData config) { + dataInput.setData(((EndsWithData) config).getData(), + Charset.forName(((EndsWithData) config).getCharset())); + } + + @Override + public boolean isValid() { + if (dataInput.getBytes().length == 0) { + Dialogs.createErrorDialog("Data required", "You have enter data."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithSubruleFactory.java new file mode 100644 index 0000000..5a7ba83 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithSubruleFactory.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.ends_with; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class EndsWithSubruleFactory extends TagSubruleFactory { + @Override + public String getCode() { + return "ends_with"; + } + + @Override + public String getName() { + return "Ends with ..."; + } + + @Override + public TagSubrule createSubrule(TagSubruleData data) { + return new EndsWithTagSubrule(this, data); + } + + @Override + public TagSubruleConfigurator createConfigPane() throws IOException { + return new EndsWithSubruleConfigurator(); + } + + @Override + public Type getConfigType() { + return EndsWithData.class; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithTagSubrule.java new file mode 100644 index 0000000..09f533e --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/ends_with/EndsWithTagSubrule.java @@ -0,0 +1,34 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.ends_with; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; +import com.warxim.petep.util.PduUtils; + +public final class EndsWithTagSubrule extends TagSubrule { + public EndsWithTagSubrule(TagSubruleFactory factory, TagSubruleData data) { + super(factory, data); + } + + @Override + public boolean test(PDU pdu) { + return PduUtils.endsWith(pdu, ((EndsWithData) data).getData()); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagData.java new file mode 100644 index 0000000..7007873 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagData.java @@ -0,0 +1,31 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.has_tag; + +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; + +public final class HasTagData extends TagSubruleData { + private final String tag; + + public HasTagData(String tag) { + this.tag = tag; + } + + public String getTag() { + return tag; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagSubruleConfigurator.java new file mode 100644 index 0000000..683d849 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagSubruleConfigurator.java @@ -0,0 +1,53 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.has_tag; + +import java.io.IOException; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.fxml.FXML; +import javafx.scene.control.TextField; + +public final class HasTagSubruleConfigurator extends TagSubruleConfigurator { + @FXML + private TextField tagInput; + + public HasTagSubruleConfigurator() throws IOException { + super("/fxml/extension/internal/tagger/factory/HasTagSubrule.fxml"); + } + + @Override + public TagSubruleData getConfig() { + return new HasTagData(tagInput.getText()); + } + + @Override + public void setConfig(TagSubruleData config) { + tagInput.setText(((HasTagData) config).getTag()); + } + + @Override + public boolean isValid() { + if (tagInput.getText().length() == 0) { + Dialogs.createErrorDialog("Tag required", "You have to enter tag."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagSubruleFactory.java new file mode 100644 index 0000000..c37b959 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagSubruleFactory.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.has_tag; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class HasTagSubruleFactory extends TagSubruleFactory { + @Override + public String getCode() { + return "tag"; + } + + @Override + public String getName() { + return "Has tag ..."; + } + + @Override + public TagSubrule createSubrule(TagSubruleData data) { + return new HasTagTagSubrule(this, data); + } + + @Override + public TagSubruleConfigurator createConfigPane() throws IOException { + return new HasTagSubruleConfigurator(); + } + + @Override + public Type getConfigType() { + return HasTagData.class; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagTagSubrule.java new file mode 100644 index 0000000..00f03ca --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/has_tag/HasTagTagSubrule.java @@ -0,0 +1,38 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.has_tag; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class HasTagTagSubrule extends TagSubrule { + public HasTagTagSubrule(TagSubruleFactory factory, TagSubruleData data) { + super(factory, data); + } + + @Override + public boolean test(PDU pdu) { + return pdu.hasTag(((HasTagData) data).getTag()); + } + + @Override + public String toString() { + return "Has tag " + ((HasTagData) data).getTag(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxyData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxyData.java new file mode 100644 index 0000000..87a9083 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxyData.java @@ -0,0 +1,31 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.proxy; + +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; + +public final class ProxyData extends TagSubruleData { + private final String proxyCode; + + public ProxyData(String proxyCode) { + this.proxyCode = proxyCode; + } + + public String getProxyCode() { + return proxyCode; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxySubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxySubruleConfigurator.java new file mode 100644 index 0000000..84c9b64 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxySubruleConfigurator.java @@ -0,0 +1,65 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.proxy; + +import java.io.IOException; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.proxy.module.ProxyModule; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.scene.control.ComboBox; + +public final class ProxySubruleConfigurator extends TagSubruleConfigurator { + @FXML + private ComboBox proxyInput; + + public ProxySubruleConfigurator(ExtensionHelper helper) throws IOException { + super("/fxml/extension/internal/tagger/factory/ProxySubrule.fxml"); + + proxyInput.setItems(FXCollections.observableList(helper.getProxyModules())); + } + + @Override + public TagSubruleData getConfig() { + return new ProxyData(proxyInput.getSelectionModel().getSelectedItem().getCode()); + } + + @Override + public void setConfig(TagSubruleData config) { + ObservableList modules = proxyInput.getItems(); + for (int i = 0; i < modules.size(); ++i) { + if (modules.get(i).getCode().equals((((ProxyData) config).getProxyCode()))) { + proxyInput.getSelectionModel().select(i); + return; + } + } + } + + @Override + public boolean isValid() { + if (proxyInput.getSelectionModel().getSelectedItem() == null) { + Dialogs.createErrorDialog("Proxy required", "You have to select proxy."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxySubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxySubruleFactory.java new file mode 100644 index 0000000..b4fa4db --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxySubruleFactory.java @@ -0,0 +1,58 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.proxy; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; +import com.warxim.petep.helper.ExtensionHelper; + +public final class ProxySubruleFactory extends TagSubruleFactory { + private ExtensionHelper helper; + + public ProxySubruleFactory(ExtensionHelper helper) { + this.helper = helper; + } + + @Override + public String getCode() { + return "proxy"; + } + + @Override + public String getName() { + return "Proxy ..."; + } + + @Override + public TagSubrule createSubrule(TagSubruleData data) { + return new ProxyTagSubrule(this, data); + } + + @Override + public TagSubruleConfigurator createConfigPane() throws IOException { + return new ProxySubruleConfigurator(helper); + } + + @Override + public Type getConfigType() { + return ProxyData.class; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxyTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxyTagSubrule.java new file mode 100644 index 0000000..7696358 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/proxy/ProxyTagSubrule.java @@ -0,0 +1,38 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.proxy; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class ProxyTagSubrule extends TagSubrule { + public ProxyTagSubrule(TagSubruleFactory factory, TagSubruleData data) { + super(factory, data); + } + + @Override + public boolean test(PDU pdu) { + return pdu.getProxy().getModule().getCode().equals(((ProxyData) data).getProxyCode()); + } + + @Override + public String toString() { + return "Proxy " + ((ProxyData) data).getProxyCode(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeData.java new file mode 100644 index 0000000..bbdef24 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeData.java @@ -0,0 +1,31 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.size; + +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; + +public final class SizeData extends TagSubruleData { + private final int size; + + public SizeData(int size) { + this.size = size; + } + + public int getSize() { + return size; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeSubruleConfigurator.java new file mode 100644 index 0000000..f0d36c9 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeSubruleConfigurator.java @@ -0,0 +1,59 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.size; + +import java.io.IOException; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.fxml.FXML; +import javafx.scene.control.TextField; + +public final class SizeSubruleConfigurator extends TagSubruleConfigurator { + @FXML + private TextField sizeInput; + + public SizeSubruleConfigurator() throws IOException { + super("/fxml/extension/internal/tagger/factory/SizeSubrule.fxml"); + } + + @Override + public TagSubruleData getConfig() { + return new SizeData(Integer.parseInt(sizeInput.getText())); + } + + @Override + public void setConfig(TagSubruleData config) { + sizeInput.setText(String.valueOf(((SizeData) config).getSize())); + } + + @Override + public boolean isValid() { + try { + int size = Integer.parseInt(sizeInput.getText()); + if (size < 0) { + Dialogs.createErrorDialog("Invalid size", "Size has to be number greater or equal to 0."); + return false; + } + } catch (NumberFormatException e) { + Dialogs.createErrorDialog("Invalid size", "Size has to be number greater or equal to 0."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeSubruleFactory.java new file mode 100644 index 0000000..c7f7133 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeSubruleFactory.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.size; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class SizeSubruleFactory extends TagSubruleFactory { + @Override + public String getCode() { + return "size"; + } + + @Override + public String getName() { + return "Size ..."; + } + + @Override + public TagSubrule createSubrule(TagSubruleData data) { + return new SizeTagSubrule(this, data); + } + + @Override + public TagSubruleConfigurator createConfigPane() throws IOException { + return new SizeSubruleConfigurator(); + } + + @Override + public Type getConfigType() { + return SizeData.class; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeTagSubrule.java new file mode 100644 index 0000000..2a2a630 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/size/SizeTagSubrule.java @@ -0,0 +1,38 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.size; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class SizeTagSubrule extends TagSubrule { + public SizeTagSubrule(TagSubruleFactory factory, TagSubruleData data) { + super(factory, data); + } + + @Override + public boolean test(PDU pdu) { + return pdu.getSize() == ((SizeData) data).getSize(); + } + + @Override + public String toString() { + return "Size equals " + ((SizeData) data).getSize(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithData.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithData.java new file mode 100644 index 0000000..2b72a02 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithData.java @@ -0,0 +1,31 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.starts_with; + +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; + +public final class StartsWithData extends TagSubruleData { + private final byte[] data; + + public StartsWithData(byte[] data) { + this.data = data; + } + + public byte[] getData() { + return data; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithSubruleConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithSubruleConfigurator.java new file mode 100644 index 0000000..ac4d714 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithSubruleConfigurator.java @@ -0,0 +1,53 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.starts_with; + +import java.io.IOException; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.gui.control.BytesEditor; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.fxml.FXML; + +public final class StartsWithSubruleConfigurator extends TagSubruleConfigurator { + @FXML + private BytesEditor dataInput; + + public StartsWithSubruleConfigurator() throws IOException { + super("/fxml/extension/internal/tagger/factory/StartsWithSubrule.fxml"); + } + + @Override + public TagSubruleData getConfig() { + return new StartsWithData(dataInput.getBytes()); + } + + @Override + public void setConfig(TagSubruleData config) { + dataInput.setBytes(((StartsWithData) config).getData()); + } + + @Override + public boolean isValid() { + if (dataInput.getBytes().length == 0) { + Dialogs.createErrorDialog("Data required", "You have enter data."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithSubruleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithSubruleFactory.java new file mode 100644 index 0000000..1b1fd35 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithSubruleFactory.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.starts_with; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleConfigurator; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; + +public final class StartsWithSubruleFactory extends TagSubruleFactory { + @Override + public String getCode() { + return "starts_with"; + } + + @Override + public String getName() { + return "Starts with ..."; + } + + @Override + public TagSubrule createSubrule(TagSubruleData data) { + return new StartsWithTagSubrule(this, data); + } + + @Override + public TagSubruleConfigurator createConfigPane() throws IOException { + return new StartsWithSubruleConfigurator(); + } + + @Override + public Type getConfigType() { + return StartsWithData.class; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithTagSubrule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithTagSubrule.java new file mode 100644 index 0000000..5c7745b --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/factory/internal/starts_with/StartsWithTagSubrule.java @@ -0,0 +1,34 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.factory.internal.starts_with; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; +import com.warxim.petep.util.PduUtils; + +public final class StartsWithTagSubrule extends TagSubrule { + public StartsWithTagSubrule(TagSubruleFactory factory, TagSubruleData data) { + super(factory, data); + } + + @Override + public boolean test(PDU pdu) { + return PduUtils.startsWith(pdu, ((StartsWithData) data).getData()); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/TagGroupController.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/TagGroupController.java new file mode 100644 index 0000000..226206b --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/TagGroupController.java @@ -0,0 +1,164 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.gui; + +import java.io.IOException; +import java.net.URL; +import java.util.Optional; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupController; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager; +import com.warxim.petep.extension.internal.tagger.gui.rule.EditTagRuleDialog; +import com.warxim.petep.extension.internal.tagger.gui.rule.NewTagRuleDialog; +import com.warxim.petep.extension.internal.tagger.rule.TagRule; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.collections.FXCollections; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; + +/** Tag group controller. */ +public final class TagGroupController extends RuleGroupController + implements Initializable { + private final TagSubruleFactoryManager moduleManager; + + @FXML + private TableView table; + + @FXML + private TableColumn nameColumn; + + @FXML + private TableColumn tagColumn; + + @FXML + private TableColumn enabledColumn; + + /** Tag group controller constructor. */ + public TagGroupController(RuleGroup group, TagSubruleFactoryManager moduleManager) { + super(group); + this.moduleManager = moduleManager; + } + + @Override + public void initialize(URL location, ResourceBundle resources) { + nameColumn.setCellValueFactory(new PropertyValueFactory<>("name")); + tagColumn.setCellValueFactory(new PropertyValueFactory<>("tag")); + enabledColumn.setCellValueFactory(new PropertyValueFactory<>("enabled")); + + table.setItems(FXCollections.observableList(group.getRules())); + } + + @FXML + private void onNewButtonClick(ActionEvent event) { + try { + NewTagRuleDialog dialog = new NewTagRuleDialog(moduleManager); + + Optional data = dialog.showAndWait(); + + if (!data.isPresent() || data.get() == null) { + return; + } + + group.addRule(data.get()); + + refresh(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during openning of tag rule dialog", e); + } + } + + @FXML + private void onEditButtonClick(ActionEvent event) { + TagRule rule = table.getSelectionModel().getSelectedItem(); + + if (rule == null) { + return; + } + + try { + EditTagRuleDialog dialog = new EditTagRuleDialog(moduleManager, rule); + + Optional data = dialog.showAndWait(); + + if (!data.isPresent() || data.get() == null) { + return; + } + + group.replace(rule, data.get()); + + refresh(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during openning of tag rule dialog", e); + } + } + + @FXML + private void onRemoveButtonClick(ActionEvent event) { + TagRule rule = table.getSelectionModel().getSelectedItem(); + + if (rule == null) { + return; + } + + // Does user really want to remove rule? + if (!Dialogs.createYesOrNoDialog("Are you sure?", + "Do you really want to remove rule '" + rule.getName() + "'?")) { + return; + } + + group.removeRule(rule); + + refresh(); + } + + @FXML + private void onMoveUpButtonClick(ActionEvent event) { + int index = table.getSelectionModel().getSelectedIndex(); + + if (index <= 0) { + return; + } + + group.swapRules(index, index - 1); + + refresh(); + } + + @FXML + private void onMoveDownButtonClick(ActionEvent event) { + int index = table.getSelectionModel().getSelectedIndex(); + + if (index == -1 || index == group.ruleCount() - 1) { + return; + } + + group.swapRules(index, index + 1); + + refresh(); + } + + private void refresh() { + table.setItems(FXCollections.observableList(group.getRules())); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/TaggerController.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/TaggerController.java new file mode 100644 index 0000000..f7bac87 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/TaggerController.java @@ -0,0 +1,68 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.gui; + +import java.io.IOException; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupController; +import com.warxim.petep.extension.internal.common.rule_group.gui.RuleGroupsController; +import com.warxim.petep.extension.internal.common.rule_group.intercept.RuleInterceptorModule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager; +import com.warxim.petep.extension.internal.tagger.intercept.TagInterceptorModule; +import com.warxim.petep.extension.internal.tagger.rule.TagRule; +import com.warxim.petep.extension.internal.tagger.rule.TagRuleGroupManager; +import com.warxim.petep.helper.ExtensionHelper; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Node; +import javafx.scene.control.TabPane; +import javafx.util.Pair; + +/** Tagger controller. */ +public final class TaggerController extends RuleGroupsController { + private final TagSubruleFactoryManager factoryManager; + + @FXML + private TabPane tabs; + + /** Tagger controller constructor. */ + public TaggerController( + TagRuleGroupManager groupManager, + ExtensionHelper extensionHelper, + TagSubruleFactoryManager factoryManager) { + super("Tagger", groupManager, extensionHelper); + this.factoryManager = factoryManager; + } + + @Override + protected Class> getInterceptorModuleClass() { + return TagInterceptorModule.class; + } + + @Override + protected Pair> createGroupTabNode(RuleGroup group) + throws IOException { + FXMLLoader fxmlLoader = + new FXMLLoader(getClass().getResource("/fxml/extension/internal/tagger/TagRuleGroup.fxml")); + + TagGroupController controller = new TagGroupController(group, factoryManager); + + fxmlLoader.setController(controller); + + return new Pair<>(fxmlLoader.load(), controller); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/EditTagRuleDialog.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/EditTagRuleDialog.java new file mode 100644 index 0000000..457dee2 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/EditTagRuleDialog.java @@ -0,0 +1,45 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.gui.rule; + +import java.io.IOException; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager; +import com.warxim.petep.extension.internal.tagger.rule.TagRule; + +/** Edit tag rule dialog. */ +public final class EditTagRuleDialog extends TagRuleDialog { + /** Edit tag rule dialog constructor. */ + public EditTagRuleDialog(TagSubruleFactoryManager moduleManager, TagRule rule) + throws IOException { + super("Edit tag rule", "Save", moduleManager); + + nameInput.setText(rule.getName()); + descriptionInput.setText(rule.getDescription()); + tagInput.setText(rule.getTag()); + enabledInput.setSelected(rule.isEnabled()); + expressionInput.setText(rule.getExpressionString()); + + for (TagSubrule subrule : rule.getSubrules()) { + subrules.add(subrule); + } + + if (!generateExpression().equals(rule.getExpressionString())) { + customExpressionInput.setSelected(true); + } + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/NewTagRuleDialog.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/NewTagRuleDialog.java new file mode 100644 index 0000000..be0ac22 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/NewTagRuleDialog.java @@ -0,0 +1,28 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.gui.rule; + +import java.io.IOException; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager; + +/** New tag rule dialog. */ +public final class NewTagRuleDialog extends TagRuleDialog { + /** New tag rule dialog constructor. */ + public NewTagRuleDialog(TagSubruleFactoryManager moduleManager) throws IOException { + super("New tag rule", "Create", moduleManager); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/TagRuleDialog.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/TagRuleDialog.java new file mode 100644 index 0000000..7fed309 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/rule/TagRuleDialog.java @@ -0,0 +1,325 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.gui.rule; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Optional; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.booleanexpressioninterpreter.ExpressionParser; +import com.warxim.booleanexpressioninterpreter.InvalidExpressionException; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager; +import com.warxim.petep.extension.internal.tagger.gui.subrule.EditTagSubruleDialog; +import com.warxim.petep.extension.internal.tagger.gui.subrule.NewTagSubruleDialog; +import com.warxim.petep.extension.internal.tagger.rule.TagRule; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.gui.dialog.SimpleInputDialog; +import javafx.beans.binding.Bindings; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.CheckBox; +import javafx.scene.control.TableCell; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; + +/** Tag rule dialog. */ +public abstract class TagRuleDialog extends SimpleInputDialog { + private static final String INDEX_REGEX = + "[^0-9()!]{0}[^0-9()!]|[^0-9()!]{0}$|^{0}$|^{0}[^0-9()!]"; + + private TagSubruleFactoryManager moduleManager; + + @FXML + protected TextField nameInput; + + @FXML + protected TextArea descriptionInput; + + @FXML + protected TextField tagInput; + + @FXML + protected CheckBox enabledInput; + + @FXML + protected TextField expressionInput; + + @FXML + protected CheckBox customExpressionInput; + + @FXML + private TableView subrulesTable; + + @FXML + private TableColumn indexColumn; + + @FXML + private TableColumn typeColumn; + + protected ObservableList subrules; + + private TagRule rule; + + /** Tag rule constructor. */ + public TagRuleDialog(String title, String okText, TagSubruleFactoryManager moduleManager) + throws IOException { + super("/fxml/extension/internal/tagger/TagRuleDialog.fxml", title, okText); + + this.moduleManager = moduleManager; + + enabledInput.setSelected(true); + + // Event when on custom expression checkbox is selected / deselected. + customExpressionInput.selectedProperty().addListener(this::onCustomExpressionSelectionChange); + + // Run prepare on expression input change. + expressionInput.focusedProperty().addListener(this::onExpressionInputFocusChange); + + // Allow only specific characters for expression input. + expressionInput.textProperty().addListener(this::onExpressionInputTextChange); + + // Index number calculation. + indexColumn.setCellFactory(this::createIndexCell); + + typeColumn.setCellValueFactory(cell -> new SimpleStringProperty(cell.getValue().toString())); + + subrules = FXCollections.observableArrayList(); + subrulesTable.setItems(subrules); + } + + /** Generates expression using logical ANDs. */ + protected final String generateExpression() { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < subrules.size(); ++i) { + builder.append(i); + builder.append(" & "); + } + + if (builder.length() > 3) { + builder.delete(builder.length() - 3, builder.length()); + } + + return builder.toString(); + } + + private final TableCell createIndexCell( + TableColumn column) { + TableCell cell = new TableCell<>(); + cell.textProperty() + .bind(Bindings.createStringBinding( + () -> cell.isEmpty() ? null : Integer.toString(cell.getIndex()), cell.emptyProperty(), + cell.indexProperty())); + return cell; + } + + private final void onCustomExpressionSelectionChange( + ObservableValue observable, + boolean oldValue, + boolean newValue) { + if (newValue) { + expressionInput.setDisable(false); + } else { + expressionInput.setDisable(true); + + refreshExpression(); + } + } + + private final void onExpressionInputTextChange( + ObservableValue observable, + String oldValue, + String newValue) { + if (!newValue.matches("\\s0-9!&\\(\\)\\{\\}\\[\\]\\|\\^")) { + expressionInput.setText(newValue.replaceAll("[^\\s0-9!&\\(\\)\\{\\}\\[\\]\\^\\|]", "")); + } + } + + private final void onExpressionInputFocusChange( + ObservableValue observable, + boolean oldValue, + boolean newValue) { + if (oldValue) { + try { + expressionInput + .setText(ExpressionParser.prepare(expressionInput.getText()).replace("! ", "!")); + } catch (InvalidExpressionException e) { + Dialogs.createErrorDialog("Expression is invalid", "Entered expression is invalid!"); + } + } + } + + /** Refreshes expression if custom expression is disabled. */ + private final void refreshExpression() { + if (!customExpressionInput.isSelected()) { + expressionInput.setText(generateExpression()); + } + } + + @FXML + private final void onNewButtonClick(ActionEvent event) { + try { + NewTagSubruleDialog dialog = new NewTagSubruleDialog(moduleManager); + + Optional data = dialog.showAndWait(); + + if (!data.isPresent() || data.get() == null) { + return; + } + + subrules.add(data.get()); + + refreshExpression(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during openning of tag rule dialog", e); + } + } + + @FXML + private final void onEditButtonClick(ActionEvent event) { + TagSubrule subrule = subrulesTable.getSelectionModel().getSelectedItem(); + + if (subrule == null) { + return; + } + + try { + EditTagSubruleDialog dialog = new EditTagSubruleDialog(moduleManager, subrule); + + Optional data = dialog.showAndWait(); + + if (!data.isPresent() || data.get() == null) { + return; + } + + subrules.set(subrules.indexOf(subrule), data.get()); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during openning of tag rule dialog", e); + } + } + + @FXML + private final void onRemoveButtonClick(ActionEvent event) { + int index = subrulesTable.getSelectionModel().getSelectedIndex(); + + if (index == -1) { + return; + } + + if (!Dialogs.createYesOrNoDialog("Are you sure?", "Do you really want to remove subrule?")) { + return; + } + + subrules.remove(index); + + if (customExpressionInput.isSelected()) { + try { + expressionInput.setText(ExpressionParser.prepare( + expressionInput.getText().replaceAll(MessageFormat.format(INDEX_REGEX, index), ""))); + } catch (InvalidExpressionException e) { + Dialogs.createErrorDialog("Expression is invalid", "Entered expression is invalid!"); + } + } else { + refreshExpression(); + } + } + + private final void swap(int what, int with) { + Collections.swap(subrules, what, with); + + if (customExpressionInput.isSelected()) { + String newExpression = expressionInput.getText() + .replace("!", "! ") + .replaceAll(MessageFormat.format(INDEX_REGEX, what), "_TMP_"); + + newExpression = + newExpression.replaceAll(MessageFormat.format(INDEX_REGEX, with), String.valueOf(what)); + + newExpression = newExpression.replace("_TMP_", String.valueOf(with)); + + try { + expressionInput.setText(ExpressionParser.prepare(newExpression).replace("! ", "!")); + } catch (InvalidExpressionException e) { + Dialogs.createErrorDialog("Expression is invalid", "Entered expression is invalid!"); + } + } + } + + /** Move instance up */ + @FXML + private final void onMoveUpButtonClick(ActionEvent event) { + int index = subrulesTable.getSelectionModel().getSelectedIndex(); + + if (index <= 0) { + return; + } + + swap(index, index - 1); + } + + /** Move instance down */ + @FXML + private final void onMoveDownButtonClick(ActionEvent event) { + int index = subrulesTable.getSelectionModel().getSelectedIndex(); + + if (index == -1 || index == subrules.size() - 1) { + return; + } + + swap(index, index + 1); + } + + @Override + protected final boolean isValid() { + // Validate name. + if (nameInput.getText().isBlank()) { + Dialogs.createErrorDialog("Name required", "You have to enter name."); + return false; + } + + // Validate tag. + if (tagInput.getText().isEmpty() || !tagInput.getText().matches("^[a-zA-Z0-9-_.]+$")) { + Dialogs.createErrorDialog("Tag required", + "You have to enter tag (allowed characters are A-Za-z0-9-_.)."); + return false; + } + + try { + rule = new TagRule(nameInput.getText(), descriptionInput.getText(), enabledInput.isSelected(), + tagInput.getText(), new ArrayList<>(subrules), expressionInput.getText()); + } catch (InvalidExpressionException e) { + Dialogs.createErrorDialog("Invalid expression", "Entered expression is not valid!"); + return false; + } + + return true; + } + + @Override + protected final TagRule obtainResult() { + return rule; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/EditTagSubruleDialog.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/EditTagSubruleDialog.java new file mode 100644 index 0000000..dc2aa37 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/EditTagSubruleDialog.java @@ -0,0 +1,50 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.gui.subrule; + +import java.io.IOException; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager; +import com.warxim.petep.gui.component.ConfigPane; + +/** Edit tag subrule dialog. */ +public final class EditTagSubruleDialog extends TagSubruleDialog { + /** Edit tag subrule dialog constructor. */ + public EditTagSubruleDialog(TagSubruleFactoryManager factoryManager, TagSubrule subrule) + throws IOException { + super("Edit tag subrule", "Save", factoryManager); + + factoryInput.getSelectionModel().select(subrule.getFactory()); + + // Load config pane. + ConfigPane pane = createFactoryPane(); + if (pane == null) { + return; + } + setFactoryPane(pane); + + // Get configuration from instance. + TagSubruleData data = subrule.getData(); + if (data == null) { + return; + } + + // Set config to pane. + pane.setConfig(data); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/NewTagSubruleDialog.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/NewTagSubruleDialog.java new file mode 100644 index 0000000..3570674 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/NewTagSubruleDialog.java @@ -0,0 +1,28 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.gui.subrule; + +import java.io.IOException; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager; + +/** New tag subrule dialog. */ +public final class NewTagSubruleDialog extends TagSubruleDialog { + /** New tag subrule dialog constructor. */ + public NewTagSubruleDialog(TagSubruleFactoryManager factoryManager) throws IOException { + super("New tag subrule", "Create", factoryManager); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/TagSubruleDialog.java b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/TagSubruleDialog.java new file mode 100644 index 0000000..ce30834 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/gui/subrule/TagSubruleDialog.java @@ -0,0 +1,134 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.gui.subrule; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleData; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactory; +import com.warxim.petep.extension.internal.tagger.factory.TagSubruleFactoryManager; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.gui.dialog.SimpleInputDialog; +import javafx.collections.FXCollections; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.ComboBox; +import javafx.scene.layout.AnchorPane; +import javafx.util.StringConverter; + +/** Tag subrule dialog. */ +public abstract class TagSubruleDialog extends SimpleInputDialog { + @FXML + protected ComboBox factoryInput; + + @FXML + protected AnchorPane factoryPane; + + /** Tag subrule dialog constructor. */ + public TagSubruleDialog(String title, String okText, TagSubruleFactoryManager factoryManager) + throws IOException { + super("/fxml/extension/internal/tagger/TagSubruleDialog.fxml", title, okText); + + // Show factory name as factory input text. + factoryInput.setConverter(new StringConverter() { + @Override + public String toString(TagSubruleFactory factory) { + if (factory == null) { + return ""; + } + return factory.getName(); + } + + @Override + public TagSubruleFactory fromString(String str) { + return null; + } + }); + + factoryInput.setItems(FXCollections.observableArrayList(factoryManager.getFactories())); + } + + protected final void setFactoryPane(ConfigPane pane) { + if (pane == null) { + // Clear factory pane if config pane does not exist. + factoryPane.getChildren().clear(); + return; + } + + AnchorPane.setLeftAnchor(pane, 0D); + AnchorPane.setRightAnchor(pane, 0D); + + // Add config pane to factory pane. + factoryPane.getChildren().setAll(pane); + } + + protected final ConfigPane createFactoryPane() { + TagSubruleFactory factory = factoryInput.getSelectionModel().getSelectedItem(); + + if (factory == null) { + return null; + } + + try { + return factory.createConfigPane(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not load factory config pane.", e); + } + + return null; + } + + @SuppressWarnings("unchecked") + @Override + protected final boolean isValid() { + // Validate factory + TagSubruleFactory factory = factoryInput.getSelectionModel().getSelectedItem(); + if (factory == null) { + Dialogs.createErrorDialog("Factory required", "You have to select factory."); + return false; + } + + // Validate configuration pane + if (!factoryPane.getChildren().isEmpty() + && !((ConfigPane) factoryPane.getChildren().get(0)).isValid()) { + return false; + } + + return true; + } + + @SuppressWarnings("unchecked") + @Override + protected final TagSubrule obtainResult() { + TagSubruleFactory factory = factoryInput.getSelectionModel().getSelectedItem(); + + if (factoryPane.getChildren().isEmpty()) { + return factory.createSubrule(null); + } else { + return factory.createSubrule( + ((ConfigPane) factoryPane.getChildren().get(0)).getConfig()); + } + } + + @FXML + private final void onFactoryChange(ActionEvent event) { + setFactoryPane(createFactoryPane()); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptor.java b/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptor.java new file mode 100644 index 0000000..3574245 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptor.java @@ -0,0 +1,61 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.intercept; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.tagger.rule.TagRule; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.worker.Interceptor; + +/** Tag interceptor. */ +public final class TagInterceptor extends Interceptor { + private final RuleGroup group; + + /** Tag interceptor constructor. */ + public TagInterceptor(int id, TagInterceptorModule module, PetepHelper helper) { + super(id, module, helper); + + this.group = module.getRuleGroup(); + } + + @Override + public boolean prepare() { + return true; + } + + @Override + public boolean intercept(PDU pdu) { + for (TagRule rule : group.getRules()) { + if (rule.test(pdu)) { + // Drop PDU if the tag is "drop". + if (rule.getTag().equals("drop")) { + return false; + } + + pdu.addTag(rule.getTag()); + } + } + + return true; + } + + @Override + public void stop() { + // No action needed. + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptorModule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptorModule.java new file mode 100644 index 0000000..1a882bb --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptorModule.java @@ -0,0 +1,64 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.intercept; + +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.config.RuleInterceptorConfig; +import com.warxim.petep.extension.internal.common.rule_group.intercept.RuleInterceptorModule; +import com.warxim.petep.extension.internal.tagger.TaggerExtension; +import com.warxim.petep.extension.internal.tagger.rule.TagRule; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.worker.Interceptor; +import com.warxim.petep.persistence.Configurable; + +/** Tag interceptor module. */ +public final class TagInterceptorModule extends RuleInterceptorModule + implements Configurable { + private RuleGroup group; + + /** Tag interceptor module constructor. */ + public TagInterceptorModule( + InterceptorModuleFactory factory, + String code, + String name, + String description, + boolean enabled) { + super(factory, code, name, description, enabled); + } + + @Override + public Interceptor createInterceptor(int id, PetepHelper helper) { + return new TagInterceptor(id, this, helper); + } + + @Override + public RuleInterceptorConfig saveConfig() { + return new RuleInterceptorConfig(group.getCode()); + } + + @Override + public void loadConfig(RuleInterceptorConfig config) { + group = ((TaggerExtension) factory.getExtension()).getRuleGroupManager() + .get(config.getRuleGroupCode()); + } + + @Override + public RuleGroup getRuleGroup() { + return group; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptorModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptorModuleFactory.java new file mode 100644 index 0000000..df921fc --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/intercept/TagInterceptorModuleFactory.java @@ -0,0 +1,60 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.intercept; + +import java.io.IOException; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.internal.common.rule_group.config.RuleInterceptorConfig; +import com.warxim.petep.extension.internal.common.rule_group.gui.RuleInterceptorConfigurator; +import com.warxim.petep.extension.internal.tagger.TaggerExtension; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.persistence.Configurator; + +/** Tag interceptor module. */ +public final class TagInterceptorModuleFactory extends InterceptorModuleFactory + implements Configurator { + /** Tag interceptor module constructor. */ + public TagInterceptorModuleFactory(Extension extension) { + super(extension); + } + + @Override + public String getCode() { + return "tagger"; + } + + @Override + public String getName() { + return "Tagger"; + } + + @Override + public InterceptorModule createModule( + String code, + String name, + String description, + boolean enabled) { + return new TagInterceptorModule(this, code, name, description, enabled); + } + + @Override + public ConfigPane createConfigPane() throws IOException { + return new RuleInterceptorConfigurator<>(((TaggerExtension) extension).getRuleGroupManager()); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/rule/PduPredicateExpression.java b/src/main/java/com/warxim/petep/extension/internal/tagger/rule/PduPredicateExpression.java new file mode 100644 index 0000000..47ebccf --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/rule/PduPredicateExpression.java @@ -0,0 +1,29 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.rule; + +import java.util.function.Predicate; +import com.warxim.booleanexpressioninterpreter.PredicateExpression; +import com.warxim.petep.core.pdu.PDU; + +/** PDU predicate expression. */ +public final class PduPredicateExpression extends PredicateExpression { + /** PDU predicate expression constructor. */ + public PduPredicateExpression(Predicate predicate) { + super(predicate); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/rule/TagRule.java b/src/main/java/com/warxim/petep/extension/internal/tagger/rule/TagRule.java new file mode 100644 index 0000000..95d463a --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/rule/TagRule.java @@ -0,0 +1,94 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.rule; + +import java.util.Collections; +import java.util.List; +import com.warxim.booleanexpressioninterpreter.Expression; +import com.warxim.booleanexpressioninterpreter.ExpressionParser; +import com.warxim.booleanexpressioninterpreter.InvalidExpressionException; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.internal.common.rule_group.Rule; +import com.warxim.petep.extension.internal.tagger.factory.TagSubrule; + +/** Tag rule. */ +public final class TagRule extends Rule { + private final String tag; + + private final List subrules; + + private final String expressionString; + + private final Expression expression; + private final PduPredicateExpression[] expressions; + + /** Tag rule constructor. */ + public TagRule( + String name, + String description, + boolean enabled, + String tag, + List subrules, + String expressionString) throws InvalidExpressionException { + super(name, description, enabled); + this.tag = tag; + this.subrules = Collections.unmodifiableList(subrules); + this.expressionString = expressionString; + + // Initialize expressions. + expressions = new PduPredicateExpression[subrules.size()]; + + for (int i = 0; i < expressions.length; ++i) { + TagSubrule subrule = subrules.get(i); + expressions[i] = new PduPredicateExpression(subrule::test); + } + + expression = ExpressionParser.parse(expressionString, expressions); + } + + public String getTag() { + return tag; + } + + public List getSubrules() { + return subrules; + } + + /* + * EXPRESSIONS + */ + public String getExpressionString() { + return expressionString; + } + + public boolean test(PDU pdu) { + if ((!enabled) || pdu.hasTag(tag)) { + return false; + } + + return testSubrules(pdu); + } + + /** Tests subrules using expression (synchronized because of the parameterized expressions). */ + public synchronized boolean testSubrules(PDU pdu) { + for (int i = 0; i < expressions.length; ++i) { + expressions[i].setParam(pdu); + } + + return expression.solve(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tagger/rule/TagRuleGroupManager.java b/src/main/java/com/warxim/petep/extension/internal/tagger/rule/TagRuleGroupManager.java new file mode 100644 index 0000000..ecc1b8a --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tagger/rule/TagRuleGroupManager.java @@ -0,0 +1,28 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tagger.rule; + +import com.warxim.petep.extension.internal.common.rule_group.RuleGroup; +import com.warxim.petep.extension.internal.common.rule_group.RuleGroupManager; + +/** Tag rule group manager. */ +public final class TagRuleGroupManager extends RuleGroupManager> { + /** Tag rule group manager constructor. */ + public TagRuleGroupManager() { + super(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/SslCertificateConfig.java b/src/main/java/com/warxim/petep/extension/internal/tcp/SslCertificateConfig.java new file mode 100644 index 0000000..b5bb343 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/SslCertificateConfig.java @@ -0,0 +1,53 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp; + +/** SSL certificate configuration. */ +public final class SslCertificateConfig { + private final String keyStore; + private final String keyStoreType; + private final String keyStorePassword; + private final String keyPassword; + + /** SSL certificate configuration constructor. */ + public SslCertificateConfig( + String keyStore, + String keyStoreType, + String keyStorePassword, + String keyPassword) { + this.keyStore = keyStore; + this.keyStoreType = keyStoreType; + this.keyStorePassword = keyStorePassword; + this.keyPassword = keyPassword; + } + + public String getKeyStore() { + return keyStore; + } + + public String getKeyStoreType() { + return keyStoreType; + } + + public String getKeyStorePassword() { + return keyStorePassword; + } + + public String getKeyPassword() { + return keyPassword; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/SslConfig.java b/src/main/java/com/warxim/petep/extension/internal/tcp/SslConfig.java new file mode 100644 index 0000000..31fe37e --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/SslConfig.java @@ -0,0 +1,37 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp; + +/** SSL configuration. */ +public final class SslConfig { + private final String algorithm; + private final SslCertificateConfig certificateConfig; + + /** SSL configuration constructor. */ + public SslConfig(String algorithm, SslCertificateConfig certificateConfig) { + this.algorithm = algorithm; + this.certificateConfig = certificateConfig; + } + + public String getAlgorithm() { + return algorithm; + } + + public SslCertificateConfig getCertificateConfig() { + return certificateConfig; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/TcpConfig.java b/src/main/java/com/warxim/petep/extension/internal/tcp/TcpConfig.java new file mode 100644 index 0000000..d5cbc1c --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/TcpConfig.java @@ -0,0 +1,92 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp; + +/** TCP configuration. */ +public final class TcpConfig { + private final String proxyIP; + private final String targetIP; + + private final int proxyPort; + private final int targetPort; + + private final int bufferSize; + private final String charset; + + private final int connectionCloseDelay; + + private final SslConfig serverSslConfig; + private final SslConfig clientSslConfig; + + /** TCP configuration constructor. */ + public TcpConfig( + String proxyIP, + String targetIP, + int proxyPort, + int targetPort, + int bufferSize, + String charset, + int connectionCloseDelay, + SslConfig serverSslConfig, + SslConfig clientSslConfig) { + this.proxyIP = proxyIP; + this.targetIP = targetIP; + this.proxyPort = proxyPort; + this.targetPort = targetPort; + this.bufferSize = bufferSize; + this.charset = charset; + this.connectionCloseDelay = connectionCloseDelay; + this.serverSslConfig = serverSslConfig; + this.clientSslConfig = clientSslConfig; + } + + public String getProxyIP() { + return proxyIP; + } + + public String getTargetIP() { + return targetIP; + } + + public int getProxyPort() { + return proxyPort; + } + + public int getTargetPort() { + return targetPort; + } + + public int getBufferSize() { + return bufferSize; + } + + public String getCharset() { + return charset; + } + + public int getConnectionCloseDelay() { + return connectionCloseDelay; + } + + public SslConfig getServerSslConfig() { + return serverSslConfig; + } + + public SslConfig getClientSslConfig() { + return clientSslConfig; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/TcpConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/tcp/TcpConfigurator.java new file mode 100644 index 0000000..d872190 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/TcpConfigurator.java @@ -0,0 +1,379 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; +import java.util.Arrays; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.util.FileUtils; +import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.ComboBox; +import javafx.scene.control.RadioButton; +import javafx.scene.control.TextField; +import javafx.scene.control.Toggle; +import javafx.scene.control.ToggleGroup; +import javafx.stage.FileChooser; + +/** TCP configurator GUI. */ +public final class TcpConfigurator extends ConfigPane { + /* + * TCP + */ + @FXML + private TextField proxyIpInput; + + @FXML + private TextField proxyPortInput; + + @FXML + private TextField targetIpInput; + + @FXML + private TextField targetPortInput; + + @FXML + private TextField bufferSizeInput; + + @FXML + private TextField charsetInput; + + @FXML + private TextField connectionCloseDelayInput; + + /* + * SSL + */ + + /* + * SERVER SSL + */ + @FXML + private ToggleGroup serverSsl; + @FXML + private RadioButton serverNoSslRadio; + @FXML + private RadioButton serverSslRadio; + + @FXML + private ComboBox serverAlgorithmInput; + + @FXML + private TextField serverKeyStoreInput; + @FXML + private TextField serverKeyStorePasswordInput; + @FXML + private TextField serverKeyPasswordInput; + @FXML + private ComboBox serverKeyStoreTypeInput; + + /* + * CLIENT SSL + */ + @FXML + private ToggleGroup clientSsl; + @FXML + private RadioButton clientNoSslRadio; + @FXML + private RadioButton clientSslRadio; + @FXML + private RadioButton clientSslWithCertificateRadio; + + @FXML + private ComboBox clientAlgorithmInput; + + @FXML + private TextField clientKeyStoreInput; + @FXML + private TextField clientKeyStorePasswordInput; + @FXML + private TextField clientKeyPasswordInput; + @FXML + private ComboBox clientKeyStoreTypeInput; + + public TcpConfigurator() throws IOException { + super("/fxml/extension/internal/tcp/TcpConfigurator.fxml"); + + proxyIpInput.setText("127.0.0.1"); + proxyPortInput.setText("8888"); + bufferSizeInput.setText("4096"); + connectionCloseDelayInput.setText("500"); + charsetInput.setText(StandardCharsets.ISO_8859_1.name()); + + /* + * SSL + */ + ObservableList algorithms = + FXCollections.observableList(Arrays.asList("SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2")); + ObservableList keyStoreTypes = + FXCollections.observableList(Arrays.asList("PKCS12", "PKCS11", "JKS")); + + /* + * SERVER SSL + */ + serverSsl.selectedToggleProperty().addListener(this::onServerSslEnabledChange); + + serverNoSslRadio.setSelected(true); + + serverAlgorithmInput.setItems(algorithms); + serverAlgorithmInput.getSelectionModel().selectLast(); + + serverKeyStoreTypeInput.setItems(keyStoreTypes); + serverKeyStoreTypeInput.getSelectionModel().selectLast(); + + serverKeyStoreInput.setText("conf/server.jks"); + + /* + * CLIENT SSL + */ + clientSsl.selectedToggleProperty().addListener(this::onClientSslEnabledChange); + + clientNoSslRadio.setSelected(true); + + clientAlgorithmInput.setItems(FXCollections.observableList(algorithms)); + clientAlgorithmInput.getSelectionModel().selectLast(); + + clientKeyStoreTypeInput.setItems(FXCollections.observableList(keyStoreTypes)); + clientKeyStoreTypeInput.getSelectionModel().selectLast(); + + clientKeyStoreInput.setText("conf/client.jks"); + } + + /** On server SSL enabled event. */ + public void onServerSslEnabledChange( + ObservableValue observable, + Toggle oldValue, + Toggle newValue) { + if (serverSslRadio.isSelected()) { + serverAlgorithmInput.setDisable(false); + serverKeyStoreInput.setDisable(false); + serverKeyStoreTypeInput.setDisable(false); + serverKeyStorePasswordInput.setDisable(false); + serverKeyPasswordInput.setDisable(false); + } else { + serverAlgorithmInput.setDisable(true); + serverKeyStoreInput.setDisable(true); + serverKeyStoreTypeInput.setDisable(true); + serverKeyStorePasswordInput.setDisable(true); + serverKeyPasswordInput.setDisable(true); + } + } + + /** On client SSL enabled event. */ + public void onClientSslEnabledChange( + ObservableValue observable, + Toggle oldValue, + Toggle newValue) { + if (clientSslWithCertificateRadio.isSelected()) { + clientAlgorithmInput.setDisable(false); + clientKeyStoreInput.setDisable(false); + clientKeyStoreTypeInput.setDisable(false); + clientKeyStorePasswordInput.setDisable(false); + clientKeyPasswordInput.setDisable(false); + } else { + clientAlgorithmInput.setDisable(!clientSslRadio.isSelected()); + clientKeyStoreInput.setDisable(true); + clientKeyStoreTypeInput.setDisable(true); + clientKeyStorePasswordInput.setDisable(true); + clientKeyPasswordInput.setDisable(true); + } + } + + /** Get TCP configuration from configurator. */ + @Override + public TcpConfig getConfig() { + // Server SSL config. + SslConfig server; + if (serverSslRadio.isSelected()) { + server = new SslConfig(serverAlgorithmInput.getValue(), + new SslCertificateConfig(serverKeyStoreInput.getText(), + serverKeyStoreTypeInput.getValue(), serverKeyStorePasswordInput.getText(), + serverKeyPasswordInput.getText())); + } else { + server = null; + } + + // Client SSL config. + SslConfig client; + if (clientSslRadio.isSelected()) { + client = new SslConfig(clientAlgorithmInput.getValue(), null); + } else if (clientSslWithCertificateRadio.isSelected()) { + client = new SslConfig(clientAlgorithmInput.getValue(), + new SslCertificateConfig(clientKeyStoreInput.getText(), + clientKeyStoreTypeInput.getValue(), clientKeyStorePasswordInput.getText(), + clientKeyPasswordInput.getText())); + } else { + client = null; + } + + return new TcpConfig(proxyIpInput.getText(), targetIpInput.getText(), + Integer.parseInt(proxyPortInput.getText()), Integer.parseInt(targetPortInput.getText()), + Integer.parseInt(bufferSizeInput.getText()), charsetInput.getText(), + Integer.parseInt(connectionCloseDelayInput.getText()), server, client); + } + + /** Sets configuration to configurator. */ + @Override + public void setConfig(TcpConfig config) { + proxyIpInput.setText(config.getProxyIP()); + targetIpInput.setText(config.getTargetIP()); + proxyPortInput.setText(String.valueOf(config.getProxyPort())); + targetPortInput.setText(String.valueOf(config.getTargetPort())); + bufferSizeInput.setText(String.valueOf(config.getBufferSize())); + charsetInput.setText(config.getCharset()); + connectionCloseDelayInput.setText(String.valueOf(config.getConnectionCloseDelay())); + + // Server SSL config. + SslConfig server = config.getServerSslConfig(); + if (server != null) { + serverSslRadio.setSelected(true); + + serverAlgorithmInput.getSelectionModel().select(server.getAlgorithm()); + + SslCertificateConfig certificateConfig = server.getCertificateConfig(); + + serverKeyStoreInput.setText(certificateConfig.getKeyStore()); + serverKeyStoreTypeInput.setValue(certificateConfig.getKeyStoreType()); + serverKeyStorePasswordInput.setText(certificateConfig.getKeyStorePassword()); + serverKeyPasswordInput.setText(certificateConfig.getKeyPassword()); + } + + // Client SSL config. + SslConfig client = config.getClientSslConfig(); + if (client != null) { + clientAlgorithmInput.getSelectionModel().select(client.getAlgorithm()); + + SslCertificateConfig certificateConfig = client.getCertificateConfig(); + + if (certificateConfig != null) { + clientSslWithCertificateRadio.setSelected(true); + clientKeyStoreInput.setText(certificateConfig.getKeyStore()); + clientKeyStoreTypeInput.setValue(certificateConfig.getKeyStoreType()); + clientKeyStorePasswordInput.setText(certificateConfig.getKeyStorePassword()); + clientKeyPasswordInput.setText(certificateConfig.getKeyPassword()); + } else { + clientSslRadio.setSelected(true); + } + } + } + + /** Are the data provided by user valid? */ + @Override + public boolean isValid() { + if (proxyIpInput.getText().length() == 0) { + Dialogs.createErrorDialog("Proxy IP required", "You have to enter proxy IP."); + return false; + } + if (proxyPortInput.getText().length() == 0) { + Dialogs.createErrorDialog("Proxy port required", "You have to enter proxy port."); + return false; + } + + if (targetIpInput.getText().length() == 0) { + Dialogs.createErrorDialog("Target IP required", "You have to enter target IP."); + return false; + } + + if (targetPortInput.getText().length() == 0) { + Dialogs.createErrorDialog("Target port required", "You have to enter target port."); + return false; + } + + if (bufferSizeInput.getText().length() == 0) { + Dialogs.createErrorDialog("Buffer size required", "You have to enter buffer size."); + return false; + } + + if (charsetInput.getText().length() == 0) { + Dialogs.createErrorDialog("Charset required", "You have to enter charset."); + return false; + } + + if (!Charset.isSupported(charsetInput.getText())) { + Dialogs.createErrorDialog("Charset not supported", "You have entered unsupported charset."); + return false; + } + + if (connectionCloseDelayInput.getText().length() == 0) { + Dialogs.createErrorDialog("Connection close delay required", + "You have to enter connection close delay."); + return false; + } + + return true; + } + + @FXML + private void onServerCertificateOpenButtonClick(ActionEvent event) { + // Choose server certificate file + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Server certificate file"); + + if (serverKeyStoreInput.getText().isBlank()) { + fileChooser.setInitialDirectory(new File(FileUtils.getProjectDirectory())); + } else { + File temp = new File(FileUtils.getProjectFileAbsolutePath(serverKeyStoreInput.getText())); + fileChooser.setInitialDirectory(temp.getParentFile()); + fileChooser.setInitialFileName(temp.getName()); + } + + File file = fileChooser.showSaveDialog(null); + if (file == null) { + return; + } + + serverKeyStoreInput.setText(Paths.get(FileUtils.getProjectDirectory()) + .toAbsolutePath() + .relativize(Paths.get(file.getAbsolutePath())) + .toString() + .replace('\\', '/')); + } + + @FXML + private void onClientCertificateOpenButtonClick(ActionEvent event) { + // Choose client certificate file + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Client certificate file"); + + if (clientKeyStoreInput.getText().isBlank()) { + fileChooser.setInitialDirectory(new File(FileUtils.getProjectDirectory())); + } else { + File temp = new File(FileUtils.getProjectFileAbsolutePath(clientKeyStoreInput.getText())); + fileChooser.setInitialDirectory(temp.getParentFile()); + fileChooser.setInitialFileName(temp.getName()); + } + + File file = fileChooser.showSaveDialog(null); + if (file == null) { + return; + } + + clientKeyStoreInput.setText(Paths.get(FileUtils.getProjectDirectory()) + .toAbsolutePath() + .relativize(Paths.get(file.getAbsolutePath())) + .toString() + .replace('\\', '/')); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/TcpExtension.java b/src/main/java/com/warxim/petep/extension/internal/tcp/TcpExtension.java new file mode 100644 index 0000000..c581e28 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/TcpExtension.java @@ -0,0 +1,66 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp; + +import java.util.logging.Logger; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.internal.tcp.proxy.TcpProxyModuleFactory; +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.helper.GuiHelper; + +/** TCP extension. */ +public final class TcpExtension extends Extension { + /** TCP extension constructor. */ + public TcpExtension(String path) { + super(path); + + Logger.getGlobal().info("TCP extension loaded."); + } + + /** Initializes TCP extension (registers TCP proxy module). */ + @Override + public void init(ExtensionHelper helper) { + helper.registerProxyModuleFactory(new TcpProxyModuleFactory(this)); + + Logger.getGlobal().info("TCP extension registered."); + } + + @Override + public void initGui(GuiHelper helper) { + // No action needed. + } + + @Override + public String getCode() { + return "tcp"; + } + + @Override + public String getName() { + return "TCP extension"; + } + + @Override + public String getDescription() { + return "TCP extension adds TCP proxy to PETEP."; + } + + @Override + public String getVersion() { + return "1.0"; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/PlainTcpConnection.java b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/PlainTcpConnection.java new file mode 100644 index 0000000..44cf781 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/PlainTcpConnection.java @@ -0,0 +1,105 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp.proxy; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.nio.charset.Charset; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.core.pdu.PduQueue; +import com.warxim.petep.extension.internal.tcp.proxy.base.TcpConnection; +import com.warxim.petep.extension.internal.tcp.proxy.base.TcpPdu; +import com.warxim.petep.proxy.worker.Proxy; + +/** TCP connection. */ +public final class PlainTcpConnection extends TcpConnection { + /** TCP connection constructor. */ + public PlainTcpConnection(int id, Proxy proxy, Socket socket) { + super(id, proxy, socket); + } + + @Override + protected void readFromServer() { + doRead(PduDestination.CLIENT, socketServer); + } + + @Override + protected void readFromClient() { + doRead(PduDestination.SERVER, socketClient); + } + + @Override + protected void writeToServer() { + doWrite(queueC2S, socketServer); + } + + @Override + protected void writeToClient() { + doWrite(queueS2C, socketClient); + } + + /** Reads data from socket and process it in PETEP. */ + private void doRead(PduDestination destination, Socket socket) { + // Size of data + int size = -1; + int bufferSize = getConfig().getBufferSize(); + Charset charset = Charset.forName(getConfig().getCharset()); + + // Buffer + byte[] buffer = new byte[bufferSize]; + + try (InputStream in = socket.getInputStream()) { + + // Read bytes to buffer and process it in PETEP. + while ((size = in.read(buffer)) != -1) { + // Create PDU from buffer + TcpPdu pdu = new TcpPdu(proxy, this, destination, buffer, size); + + // Set configured charset. + pdu.setCharset(charset); + + // Process PDU in PETEP. + process(pdu); + + // Create new buffer. + buffer = new byte[bufferSize]; + } + } catch (IOException e) { + // Closed + } + } + + /** Writes data to socket. */ + private void doWrite(PduQueue queue, Socket socket) { + // PDU + PDU pdu; + + try (OutputStream out = socket.getOutputStream()) { + // Read bytes to buffer and send it to out stream. + while ((pdu = queue.take()) != null) { + out.write(pdu.getBuffer(), 0, pdu.getSize()); + } + } catch (IOException e) { + // Closed socket + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/PlainTcpProxy.java b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/PlainTcpProxy.java new file mode 100644 index 0000000..b7b9a29 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/PlainTcpProxy.java @@ -0,0 +1,36 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp.proxy; + +import java.net.Socket; +import com.warxim.petep.extension.internal.tcp.TcpConfig; +import com.warxim.petep.extension.internal.tcp.proxy.base.TcpConnection; +import com.warxim.petep.extension.internal.tcp.proxy.base.TcpProxy; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.proxy.module.ProxyModule; + +/** TCP Proxy. */ +public final class PlainTcpProxy extends TcpProxy { + public PlainTcpProxy(ProxyModule module, PetepHelper helper, TcpConfig config) { + super(module, helper, config); + } + + @Override + protected TcpConnection createConnection(Socket socket) { + return new PlainTcpConnection(connectionManager.nextId(), this, socket); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/TcpProxyModule.java b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/TcpProxyModule.java new file mode 100644 index 0000000..c469310 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/TcpProxyModule.java @@ -0,0 +1,54 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp.proxy; + +import com.warxim.petep.extension.internal.tcp.TcpConfig; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.persistence.Configurable; +import com.warxim.petep.proxy.factory.ProxyModuleFactory; +import com.warxim.petep.proxy.module.ProxyModule; +import com.warxim.petep.proxy.worker.Proxy; + +/** TCP proxy module. */ +public final class TcpProxyModule extends ProxyModule implements Configurable { + private TcpConfig config; + + /** TCP proxy module constructor. */ + public TcpProxyModule( + ProxyModuleFactory factory, + String code, + String name, + String description, + boolean enabled) { + super(factory, code, name, description, enabled); + } + + @Override + public Proxy createProxy(PetepHelper helper) { + return new PlainTcpProxy(this, helper, config); + } + + @Override + public TcpConfig saveConfig() { + return config; + } + + @Override + public void loadConfig(TcpConfig config) { + this.config = config; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/TcpProxyModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/TcpProxyModuleFactory.java new file mode 100644 index 0000000..5529932 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/TcpProxyModuleFactory.java @@ -0,0 +1,97 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp.proxy; + +import java.io.IOException; +import java.util.Map; +import java.util.Set; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.internal.tcp.TcpConfig; +import com.warxim.petep.extension.internal.tcp.TcpConfigurator; +import com.warxim.petep.extension.internal.tcp.proxy.base.TcpPdu; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.gui.component.PduMetadataPane; +import com.warxim.petep.persistence.Configurator; +import com.warxim.petep.proxy.factory.ProxyModuleFactory; +import com.warxim.petep.proxy.module.ProxyModule; +import com.warxim.petep.proxy.serizalization.ProxyDeserializer; +import com.warxim.petep.proxy.serizalization.ProxySerializer; +import com.warxim.petep.proxy.worker.Proxy; + +/** TCP proxy module. */ +public final class TcpProxyModuleFactory extends ProxyModuleFactory + implements Configurator, ProxyDeserializer, ProxySerializer { + /** TCP proxy module constructor. */ + public TcpProxyModuleFactory(Extension extension) { + super(extension); + } + + @Override + public String getName() { + return "TCP"; + } + + @Override + public String getCode() { + return "tcp"; + } + + @Override + public ProxyModule createModule(String code, String name, String description, boolean enabled) { + return new TcpProxyModule(this, code, name, description, enabled); + } + + @Override + public ConfigPane createConfigPane() throws IOException { + return new TcpConfigurator(); + } + + @Override + public PduMetadataPane createPduMetadataPane() throws IOException { + return null; + } + + @Override + public ProxySerializer getSerializer() { + return this; + } + + @Override + public ProxyDeserializer getDeserializer() { + return this; + } + + @Override + public Map serializePduMetadata(PDU pdu) { + return null; + } + + @Override + public PDU deserializePdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size, + Set tags, + Map serializedMetaData) { + return new TcpPdu(proxy, connection, destination, buffer, size, tags); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpConnection.java b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpConnection.java new file mode 100644 index 0000000..865299a --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpConnection.java @@ -0,0 +1,155 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp.proxy.base; + +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.extension.internal.tcp.TcpConfig; +import com.warxim.petep.proxy.worker.Proxy; + +public abstract class TcpConnection extends Connection { + /** Writers and readers executor. */ + protected final ExecutorService executor; + + /** Socket between client and proxy. */ + protected final Socket socketClient; + + /** Socket between proxy and server. */ + protected Socket socketServer; + + /** Is connection in closing state? */ + protected boolean closing = false; + + /** TCP connection constructor. */ + public TcpConnection(int id, Proxy proxy, Socket socket) { + super(id, proxy); + socketClient = socket; + executor = Executors.newFixedThreadPool(4); + } + + /** Starts connection. */ + @Override + public boolean start() { + Logger.getGlobal().info("Starting TCP connection " + id + "..."); + + // Open connection with server + try { + socketServer = ((TcpProxy) proxy).getSocketFactory() + .createSocket(((TcpProxy) proxy).getConfig().getTargetIP(), + ((TcpProxy) proxy).getConfig().getTargetPort()); + + // Write threads + executor.execute(this::writeToServer); + executor.execute(this::writeToClient); + + // Read threads + executor.execute(this::readFromClient); + executor.execute(this::readFromServer); + + // Automatic cleanup + executor.execute(this::cleanup); + + Logger.getGlobal().info("TCP connection " + id + " started."); + + return true; + } catch (UnknownHostException e) { + Logger.getGlobal().log(Level.SEVERE, "TCP connection exception - unknown host!", e); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "TCP connection exception - IO exception!", e); + } + + return false; + } + + protected abstract void readFromServer(); + + protected abstract void readFromClient(); + + protected abstract void writeToServer(); + + protected abstract void writeToClient(); + + /** Stops connection. */ + @Override + public void stop() { + // Do not run stop if the connection is already closing. + if (closing) { + return; + } + + Logger.getGlobal().info("Stopping TCP connection " + id + "..."); + + // Enable closing state. + closing = true; + + // Shutdown threads. + executor.shutdownNow(); + + // Close socket to client. + try { + if (socketClient != null) { + socketClient.close(); + } + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "TCP connection exception - IO exception!", e); + } + + // Close socket to server. + try { + if (socketServer != null) { + socketServer.close(); + } + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "TCP connection exception - IO exception!", e); + } + + // Remove connection from connection manager. + ((TcpConnectionManager) proxy.getConnectionManager()).remove(this); + + Logger.getGlobal().info("TCP connection " + id + " stopped."); + } + + /** Cleans up connection. */ + private void cleanup() { + // Wait for remaining data processing before the connection is permanently closed. + try { + Thread.sleep(((TcpProxy) proxy).getConfig().getConnectionCloseDelay()); + } catch (InterruptedException e) { + // Interrupted + Thread.currentThread().interrupt(); + } + + stop(); + } + + /** About connection. */ + @Override + public String toString() { + return "TCP connection " + id + " (" + socketClient.getInetAddress().getHostAddress() + ":" + + socketClient.getPort() + ")"; + } + + protected TcpConfig getConfig() { + return ((TcpProxy) proxy).getConfig(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpConnectionManager.java b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpConnectionManager.java new file mode 100644 index 0000000..6150e9e --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpConnectionManager.java @@ -0,0 +1,23 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp.proxy.base; + +import com.warxim.petep.core.connection.DefaultConnectionManager; + +/** TCP connection manager. */ +public class TcpConnectionManager extends DefaultConnectionManager { +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpPdu.java b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpPdu.java new file mode 100644 index 0000000..7bdb65b --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpPdu.java @@ -0,0 +1,44 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp.proxy.base; + +import java.util.Set; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.DefaultPdu; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.proxy.worker.Proxy; + +public class TcpPdu extends DefaultPdu { + public TcpPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size) { + super(proxy, connection, destination, buffer, size); + } + + public TcpPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size, + Set tags) { + super(proxy, connection, destination, buffer, size, tags); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpProxy.java b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpProxy.java new file mode 100644 index 0000000..35e7c42 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpProxy.java @@ -0,0 +1,165 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp.proxy.base; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.core.connection.ConnectionManager; +import com.warxim.petep.extension.internal.tcp.TcpConfig; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.proxy.module.ProxyModule; +import com.warxim.petep.proxy.worker.Proxy; + +public abstract class TcpProxy extends Proxy { + /** TCP connection manager. */ + protected final TcpConnectionManager connectionManager; + + /** TCP configuration. */ + protected final TcpConfig config; + + /** Socket factory for SSL/noSSL sockets. */ + protected TcpSocketFactory socketFactory; + + /** Server socket (between client and proxy). */ + protected ServerSocket socket = null; + + /** TCP proxy thread. */ + protected Thread thread; + + /** Is TCP proxy running? */ + protected boolean running; + + /** TCP proxy constructor. */ + public TcpProxy(ProxyModule module, PetepHelper helper, TcpConfig config) { + super(module, helper); + this.config = config; + connectionManager = createConnectionManager(); + } + + /** Creates connection manager. */ + protected TcpConnectionManager createConnectionManager() { + return new TcpConnectionManager(); + } + + /** Creates connection. */ + protected abstract TcpConnection createConnection(Socket socket); + + /** Prepares TCP socket factory using SSL configuration. */ + @Override + public boolean prepare() { + try { + socketFactory = + new TcpSocketFactory(config.getServerSslConfig(), config.getClientSslConfig()); + } catch (KeyManagementException | NoSuchAlgorithmException | UnrecoverableKeyException + | KeyStoreException | CertificateException | IOException e) { + Logger.getGlobal().log(Level.SEVERE, "SSL exception.", e); + return false; + } + + return true; + } + + /** Starts TCP proxy. */ + @Override + public boolean start() { + try { + socket = socketFactory.createServerSocket(config.getProxyIP(), config.getProxyPort()); + + thread = new Thread(this::accept); + + running = true; + + thread.start(); + + return true; + } catch (UnknownHostException e) { + Logger.getGlobal().log(Level.SEVERE, "TCP unknown host exception thrown.", e); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "TCP IO exception thrown.", e); + } + + return false; + } + + /** Accepts incoming connections. */ + protected void accept() { + try { + while (running) { + // Accept connection. + TcpConnection connection = createConnection(socket.accept()); + + // Start connection and add it to connection manager. + if (connection.start()) { + connectionManager.add(connection); + } + } + } catch (SocketException e) { + // Socket closed + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "TCP Proxy accept exception.", e); + } + } + + /** Stops TCP proxy. */ + @Override + public void stop() { + running = false; + + // Interrupt accepting thread. + if (thread != null) { + thread.interrupt(); + } + + // Close server socket. + if (socket != null) { + try { + socket.close(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "TCP proxy exception - IO exception!", e); + } + } + + // Stop connections. + connectionManager.stop(); + } + + /** Returns connection manager. */ + @Override + public ConnectionManager getConnectionManager() { + return connectionManager; + } + + /** Returns TCP config. */ + public TcpConfig getConfig() { + return config; + } + + /** Returns TCP socket factory. */ + public TcpSocketFactory getSocketFactory() { + return socketFactory; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpSocketFactory.java b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpSocketFactory.java new file mode 100644 index 0000000..7c6d780 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/tcp/proxy/base/TcpSocketFactory.java @@ -0,0 +1,165 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.tcp.proxy.base; + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.Security; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ServerSocketFactory; +import javax.net.SocketFactory; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509ExtendedTrustManager; +import com.warxim.petep.extension.internal.tcp.SslCertificateConfig; +import com.warxim.petep.extension.internal.tcp.SslConfig; +import com.warxim.petep.util.FileUtils; + +/** TCP socket factory. */ +public final class TcpSocketFactory { + // Factories + private final ServerSocketFactory serverSocketFactory; + private final SocketFactory clientSocketFactory; + + /** TCP socket factory constructor. */ + public TcpSocketFactory(SslConfig server, SslConfig client) + throws NoSuchAlgorithmException, KeyManagementException, UnrecoverableKeyException, + KeyStoreException, IOException, CertificateException { + TrustManager[] truster; + + if (server != null || client != null) { + // Unset disabled algorithms. + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + + truster = createTrustManagers(); + } else { + truster = null; + } + + // Initialize server socket factory. + if (server != null) { + SSLContext serverSslContext = SSLContext.getInstance(server.getAlgorithm()); + serverSslContext.init(getKeyManagers(server.getCertificateConfig()), truster, + new java.security.SecureRandom()); + serverSocketFactory = serverSslContext.getServerSocketFactory(); + } else { + serverSocketFactory = ServerSocketFactory.getDefault(); + } + + // Initialize client socket factory. + if (client != null) { + SSLContext clientSslContext = SSLContext.getInstance(client.getAlgorithm()); + clientSslContext.init(getKeyManagers(client.getCertificateConfig()), truster, + new java.security.SecureRandom()); + clientSocketFactory = clientSslContext.getSocketFactory(); + } else { + clientSocketFactory = SocketFactory.getDefault(); + } + } + + /** Creates key managers. */ + private static final KeyManager[] getKeyManagers(SslCertificateConfig config) + throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException, + UnrecoverableKeyException { + if (config == null) { + return null; + } + + // Create key manager factory. + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); + + // Initialize key stores. + try (FileInputStream in = + new FileInputStream(FileUtils.getProjectFileAbsolutePath(config.getKeyStore()))) { + KeyStore keyStore = KeyStore.getInstance(config.getKeyStoreType()); + + keyStore.load(in, config.getKeyStorePassword().toCharArray()); + + keyManagerFactory.init(keyStore, config.getKeyPassword().toCharArray()); + } + + return keyManagerFactory.getKeyManagers(); + } + + /** Creates trust manager that trusts everything. */ + private static final TrustManager[] createTrustManagers() { + return new TrustManager[] {new X509ExtendedTrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] x509Certificates, String s) { + // Trust everyone. + } + + @Override + public void checkServerTrusted(X509Certificate[] x509Certificates, String s) { + // Trust everyone. + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket) { + // Trust everyone. + } + + @Override + public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket) { + // Trust everyone. + } + + @Override + public void checkClientTrusted( + X509Certificate[] x509Certificates, + String s, + SSLEngine sslEngine) { + // Trust everyone. + } + + @Override + public void checkServerTrusted( + X509Certificate[] x509Certificates, + String s, + SSLEngine sslEngine) { + // Trust everyone. + } + }}; + } + + /** Creates server socket for specified ip and port. */ + public ServerSocket createServerSocket(String ip, int port) throws IOException { + return serverSocketFactory.createServerSocket(port, 0, InetAddress.getByName(ip)); + } + + /** Creates socket for specified ip and port. */ + public Socket createSocket(String ip, int port) throws IOException { + return clientSocketFactory.createSocket(ip, port); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/test/TestConnection.java b/src/main/java/com/warxim/petep/extension/internal/test/TestConnection.java new file mode 100644 index 0000000..cac0aa5 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/test/TestConnection.java @@ -0,0 +1,131 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.test; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.Logger; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.core.pdu.PduQueue; +import com.warxim.petep.proxy.worker.Proxy; +import com.warxim.petep.util.PduUtils; + +public final class TestConnection extends Connection { + private boolean running; + private final ExecutorService executor; + + public TestConnection(int id, Proxy proxy) { + super(id, proxy); + executor = Executors.newFixedThreadPool(4); + } + + @Override + public boolean start() { + running = true; + + executor.execute(() -> doWrite('A', queueC2S)); + executor.execute(() -> doWrite('B', queueS2C)); + executor.execute(() -> doRead('A')); + executor.execute(() -> doRead('B')); + + Logger.getGlobal().info("Test connection " + id + " started."); + + return true; + } + + private boolean testPdu(TestPdu pdu) { + byte[] data = pdu.getBuffer(); + byte[] expected = ((TestProxy) proxy).getConfig().getBytesToReceive(); + + if (data.length != expected.length) { + return false; + } + + for (int i = 0; i < data.length; ++i) { + if (data[i] != expected[i]) { + return false; + } + } + + if (!pdu.hasTag("test_tag_1") || !pdu.hasTag("test_tag_2")) { + return false; + } + + return pdu.hasTag("test_tag_1") && pdu.hasTag("test_tag_2") + && pdu.getTest().equals("test_string"); + } + + public void doRead(char direction) { + PduDestination destination = (direction == 'A') ? PduDestination.SERVER : PduDestination.CLIENT; + + while (running) { + + TestPdu pdu = + new TestPdu(proxy, this, destination, ((TestProxy) proxy).getConfig().getBytesToSend(), + ((TestProxy) proxy).getConfig().getBytesToSend().length, "test_string"); + + pdu.addTag("test_tag_1"); + pdu.addTag("test_tag_2"); + + process(pdu); + + Logger.getGlobal().info("Test connection " + id + " sent data to PETEP [" + direction + "]."); + + try { + Thread.sleep(((TestProxy) proxy).getConfig().getSendDelay()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + } + } + + public void doWrite(char direction, PduQueue queue) { + try { + TestPdu pdu; + + while ((pdu = (TestPdu) queue.take()) != null) { + if (testPdu(pdu)) { + Logger.getGlobal() + .info("Test connection " + id + " sent data to the black hole [" + direction + "]."); + } else { + Logger.getGlobal() + .severe("Test connection " + id + " detected corrupted data [" + direction + "]: " + + PduUtils.bufferToString(pdu)); + } + } + } catch (InterruptedException e) { + // Shutdown + Thread.currentThread().interrupt(); + } + } + + @Override + public void stop() { + Logger.getGlobal().info("Stopping test connection " + id + "..."); + running = false; + + // Shutdown threads. + executor.shutdownNow(); + + // Remove connection from connection manager. + ((TestConnectionManager) proxy.getConnectionManager()).remove(this); + + Logger.getGlobal().info("Test connection " + id + " stopped."); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/test/TestConnectionManager.java b/src/main/java/com/warxim/petep/extension/internal/test/TestConnectionManager.java new file mode 100644 index 0000000..a15668c --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/test/TestConnectionManager.java @@ -0,0 +1,22 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.test; + +import com.warxim.petep.core.connection.DefaultConnectionManager; + +public final class TestConnectionManager extends DefaultConnectionManager { +} diff --git a/src/main/java/com/warxim/petep/extension/internal/test/TestExtension.java b/src/main/java/com/warxim/petep/extension/internal/test/TestExtension.java new file mode 100644 index 0000000..f4f4f35 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/test/TestExtension.java @@ -0,0 +1,62 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.test; + +import java.util.logging.Logger; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.helper.ExtensionHelper; +import com.warxim.petep.helper.GuiHelper; + +public final class TestExtension extends Extension { + public TestExtension(String path) { + super(path); + + Logger.getGlobal().info("Test extension created."); + } + + @Override + public void init(ExtensionHelper helper) { + Logger.getGlobal().info("Test extension registered."); + + helper.registerProxyModuleFactory(new TestProxyModuleFactory(this)); + } + + @Override + public String getCode() { + return "test"; + } + + @Override + public String getName() { + return "Test extension"; + } + + @Override + public String getDescription() { + return "Internal extension for testing of modules."; + } + + @Override + public String getVersion() { + return "0.1"; + } + + @Override + public void initGui(GuiHelper helper) { + // No action needed. + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/test/TestPdu.java b/src/main/java/com/warxim/petep/extension/internal/test/TestPdu.java new file mode 100644 index 0000000..51f58c1 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/test/TestPdu.java @@ -0,0 +1,68 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.test; + +import java.util.Set; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.DefaultPdu; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.proxy.worker.Proxy; + +public final class TestPdu extends DefaultPdu { + private String test; + + public TestPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size, + String test) { + super(proxy, connection, destination, buffer, size); + this.test = test; + } + + public TestPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size, + Set tags, + String test) { + super(proxy, connection, destination, buffer, size, tags); + this.test = test; + } + + public String getTest() { + return test; + } + + public void setTest(String test) { + this.test = test; + } + + @Override + public PDU copy() { + PDU pdu = new TestPdu(proxy, connection, destination, buffer.clone(), size, test); + + pdu.addTags(tags); + + return pdu; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/test/TestPduMetadataPane.java b/src/main/java/com/warxim/petep/extension/internal/test/TestPduMetadataPane.java new file mode 100644 index 0000000..ae87dde --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/test/TestPduMetadataPane.java @@ -0,0 +1,55 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.test; + +import java.io.IOException; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.gui.component.PduMetadataPane; +import com.warxim.petep.proxy.worker.Proxy; +import javafx.fxml.FXML; +import javafx.scene.control.TextField; + +public final class TestPduMetadataPane extends PduMetadataPane { + @FXML + private TextField testInput; + + public TestPduMetadataPane() throws IOException { + super("/fxml/extension/internal/test/TestPduMetadata.fxml"); + } + + @Override + public PDU getPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size) { + return new TestPdu(proxy, connection, destination, buffer, size, testInput.getText()); + } + + @Override + public void setPdu(PDU pdu) { + testInput.setText(((TestPdu) pdu).getTest()); + } + + @Override + public void clear() { + testInput.clear(); + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/test/TestProxy.java b/src/main/java/com/warxim/petep/extension/internal/test/TestProxy.java new file mode 100644 index 0000000..c128453 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/test/TestProxy.java @@ -0,0 +1,63 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.test; + +import com.warxim.petep.core.connection.ConnectionManager; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.proxy.worker.Proxy; + +public final class TestProxy extends Proxy { + private final TestProxyConfig config; + private final TestConnectionManager connectionManager; + + public TestProxy(TestProxyModule module, PetepHelper helper, TestProxyConfig config) { + super(module, helper); + this.config = config; + this.connectionManager = new TestConnectionManager(); + } + + @Override + public boolean prepare() { + return true; + } + + @Override + public boolean start() { + for (int i = 0; i < config.getNumberOfConnections(); ++i) { + TestConnection connection = new TestConnection(connectionManager.nextId(), this); + + if (connection.start()) { + connectionManager.add(connection); + } + } + return true; + } + + @Override + public void stop() { + connectionManager.stop(); + } + + @Override + public ConnectionManager getConnectionManager() { + return connectionManager; + } + + public TestProxyConfig getConfig() { + return config; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/test/TestProxyConfig.java b/src/main/java/com/warxim/petep/extension/internal/test/TestProxyConfig.java new file mode 100644 index 0000000..0947c99 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/test/TestProxyConfig.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.test; + +public final class TestProxyConfig { + private final int numberOfConnections; + private final int sendDelay; + private final byte[] bytesToSend; + private final byte[] bytesToReceive; + + public TestProxyConfig( + byte[] bytesToSend, + byte[] bytesToReceive, + int numberOfConnections, + int sendDelay) { + this.bytesToSend = bytesToSend; + this.bytesToReceive = bytesToReceive; + this.numberOfConnections = numberOfConnections; + this.sendDelay = sendDelay; + } + + public byte[] getBytesToSend() { + return bytesToSend; + } + + public byte[] getBytesToReceive() { + return bytesToReceive; + } + + public int getNumberOfConnections() { + return numberOfConnections; + } + + public int getSendDelay() { + return sendDelay; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/test/TestProxyConfigurator.java b/src/main/java/com/warxim/petep/extension/internal/test/TestProxyConfigurator.java new file mode 100644 index 0000000..0b66fcb --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/test/TestProxyConfigurator.java @@ -0,0 +1,92 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.test; + +import java.io.IOException; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.gui.control.BytesEditor; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.fxml.FXML; +import javafx.scene.control.TextField; + +public final class TestProxyConfigurator extends ConfigPane { + + @FXML + private BytesEditor sendInput; + + @FXML + private BytesEditor receiveInput; + + @FXML + private TextField connectionsInput; + + @FXML + private TextField delayInput; + + public TestProxyConfigurator() throws IOException { + super("/fxml/extension/internal/test/TestProxyConfigurator.fxml"); + } + + @Override + public TestProxyConfig getConfig() { + return new TestProxyConfig(sendInput.getBytes(), receiveInput.getBytes(), + Integer.parseInt(connectionsInput.getText()), Integer.parseInt(delayInput.getText())); + } + + @Override + public void setConfig(TestProxyConfig config) { + sendInput.setBytes(config.getBytesToSend()); + receiveInput.setBytes(config.getBytesToReceive()); + connectionsInput.setText(String.valueOf(config.getNumberOfConnections())); + delayInput.setText(String.valueOf(config.getSendDelay())); + } + + @Override + public boolean isValid() { + if (sendInput.getBytes().length == 0) { + Dialogs.createErrorDialog("Send data required", "You have to enter send data."); + return false; + } + + if (receiveInput.getBytes().length == 0) { + Dialogs.createErrorDialog("Reive data required", "You have to enter receive data."); + return false; + } + + try { + if (Integer.parseInt(connectionsInput.getText()) <= 0) { + Dialogs.createErrorDialog("Invalid number of connections", + "Number of connections has to be number > 0."); + } + } catch (NumberFormatException e) { + Dialogs.createErrorDialog("Invalid number of connections", + "Number of connections has to be number > 0."); + return false; + } + + try { + if (Integer.parseInt(delayInput.getText()) < 0) { + Dialogs.createErrorDialog("Invalid send delay", "Send delay has to be number >= 0."); + } + } catch (NumberFormatException e) { + Dialogs.createErrorDialog("Invalid send delay", "Send delay has to be number >= 0."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/test/TestProxyModule.java b/src/main/java/com/warxim/petep/extension/internal/test/TestProxyModule.java new file mode 100644 index 0000000..31d6ff9 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/test/TestProxyModule.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.test; + +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.persistence.Configurable; +import com.warxim.petep.proxy.factory.ProxyModuleFactory; +import com.warxim.petep.proxy.module.ProxyModule; +import com.warxim.petep.proxy.worker.Proxy; + +public final class TestProxyModule extends ProxyModule implements Configurable { + private TestProxyConfig config; + + public TestProxyModule( + ProxyModuleFactory factory, + String code, + String name, + String description, + boolean enabled) { + super(factory, code, name, description, enabled); + } + + @Override + public Proxy createProxy(PetepHelper helper) { + return new TestProxy(this, helper, config); + } + + @Override + public TestProxyConfig saveConfig() { + return config; + } + + @Override + public void loadConfig(TestProxyConfig config) { + this.config = config; + } +} diff --git a/src/main/java/com/warxim/petep/extension/internal/test/TestProxyModuleFactory.java b/src/main/java/com/warxim/petep/extension/internal/test/TestProxyModuleFactory.java new file mode 100644 index 0000000..49a0004 --- /dev/null +++ b/src/main/java/com/warxim/petep/extension/internal/test/TestProxyModuleFactory.java @@ -0,0 +1,93 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.extension.internal.test; + +import java.io.IOException; +import java.util.Map; +import java.util.Set; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.gui.component.PduMetadataPane; +import com.warxim.petep.persistence.Configurator; +import com.warxim.petep.proxy.factory.ProxyModuleFactory; +import com.warxim.petep.proxy.module.ProxyModule; +import com.warxim.petep.proxy.serizalization.ProxyDeserializer; +import com.warxim.petep.proxy.serizalization.ProxySerializer; +import com.warxim.petep.proxy.worker.Proxy; + +public final class TestProxyModuleFactory extends ProxyModuleFactory + implements Configurator, ProxyDeserializer, ProxySerializer { + public TestProxyModuleFactory(Extension extension) { + super(extension); + } + + @Override + public String getName() { + return "Test proxy module."; + } + + @Override + public String getCode() { + return "test"; + } + + @Override + public ProxyModule createModule(String code, String name, String description, boolean enabled) { + return new TestProxyModule(this, code, name, description, enabled); + } + + @Override + public ConfigPane createConfigPane() throws IOException { + return new TestProxyConfigurator(); + } + + @Override + public PduMetadataPane createPduMetadataPane() throws IOException { + return new TestPduMetadataPane(); + } + + @Override + public ProxySerializer getSerializer() { + return this; + } + + @Override + public ProxyDeserializer getDeserializer() { + return this; + } + + @Override + public Map serializePduMetadata(PDU pdu) { + return Map.of("Test", ((TestPdu) pdu).getTest()); + } + + @Override + public PDU deserializePdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size, + Set tags, + Map serializedMetaData) { + return new TestPdu(proxy, connection, destination, buffer, size, tags, + serializedMetaData.get("Test")); + } +} diff --git a/src/main/java/com/warxim/petep/gui/GuiBundle.java b/src/main/java/com/warxim/petep/gui/GuiBundle.java new file mode 100644 index 0000000..17dde84 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/GuiBundle.java @@ -0,0 +1,81 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui; + +import com.warxim.petep.gui.controller.ApplicationController; +import com.warxim.petep.gui.controller.settings.SettingsController; +import com.warxim.petep.gui.guide.GuideManager; +import javafx.scene.image.Image; + +/** Singleton for GUI assets. */ +public final class GuiBundle { + private static GuiBundle instance = null; + + // Assets. + private final Image petepIcon = new Image(getClass().getResourceAsStream("/img/Logo.png")); + + // GUI components. + private ApplicationController applicationController; + private SettingsController settingsController; + + // Guide manager. + private final GuideManager guideManager; + + /** GUI Bundle constructor (hidden). */ + private GuiBundle() { + guideManager = new GuideManager(); + } + + /** Returns GuiBundle instance. */ + public static GuiBundle getInstance() { + if (instance == null) { + instance = new GuiBundle(); + } + + return instance; + } + + /* + * GETTERS + */ + public Image getPetepIcon() { + return petepIcon; + } + + public ApplicationController getApplicationController() { + return applicationController; + } + + public SettingsController getSettingsController() { + return settingsController; + } + + public GuideManager getGuideManager() { + return guideManager; + } + + /* + * SETTERS + */ + public void setApplicationController(ApplicationController controller) { + applicationController = controller; + } + + public void setSettingsController(SettingsController controller) { + settingsController = controller; + } +} diff --git a/src/main/java/com/warxim/petep/gui/PetepApplication.java b/src/main/java/com/warxim/petep/gui/PetepApplication.java new file mode 100644 index 0000000..6455b23 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/PetepApplication.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui; + +import com.warxim.petep.Bundle; +import com.warxim.petep.common.Constant; +import com.warxim.petep.core.PetepManager; +import com.warxim.petep.core.PetepState; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.util.WebApiUtils; +import javafx.application.Application; +import javafx.stage.Stage; + +public class PetepApplication extends Application { + @Override + public void start(Stage stage) throws Exception { + throw new UnsupportedOperationException("Application.start() method is not implemented."); + } + + @Override + public void stop() throws Exception { + super.stop(); + + // Close PETEP if running. + PetepManager petepManager = Bundle.getInstance().getPetepManager(); + if (petepManager != null && petepManager.getState() != PetepState.STOPPED) { + Bundle.getInstance().getPetepManager().stop(); + } + } + + protected void processVersionCheck() { + String version = WebApiUtils.getLatestVersion(); + if (!version.equals(Constant.VERSION)) { + Dialogs.createNewVersionDialog(version); + } + } +} diff --git a/src/main/java/com/warxim/petep/gui/PetepGui.java b/src/main/java/com/warxim/petep/gui/PetepGui.java new file mode 100644 index 0000000..fc2ef34 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/PetepGui.java @@ -0,0 +1,60 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.sun.javafx.css.StyleManager; +import com.warxim.petep.Bundle; +import com.warxim.petep.common.Constant; +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.stage.Stage; + +/** JavaFX Application class for GUI. */ +public final class PetepGui extends PetepApplication { + @Override + public void start(Stage stage) { + // Load stylesheets. + Application.setUserAgentStylesheet(Application.STYLESHEET_MODENA); + StyleManager.getInstance() + .addUserAgentStylesheet(getClass().getResource("/css/Main.css").toString()); + + // Load application GUI. + try { + Parent root = FXMLLoader.load(getClass().getResource("/fxml/Application.fxml")); + + Scene scene = new Scene(root); + scene.getStylesheets().add("/css/Main.css"); + stage.getIcons().add(GuiBundle.getInstance().getPetepIcon()); + stage.setTitle( + "PETEP v" + Constant.VERSION + " (" + Bundle.getInstance().getProject().getName() + ")"); + stage.setWidth(1000); + stage.setHeight(700); + stage.setScene(scene); + + stage.show(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not load PETEP gui. ", e); + } + + processVersionCheck(); + } +} diff --git a/src/main/java/com/warxim/petep/gui/component/ConfigPane.java b/src/main/java/com/warxim/petep/gui/component/ConfigPane.java new file mode 100644 index 0000000..aa1287f --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/component/ConfigPane.java @@ -0,0 +1,44 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.component; + +import java.io.IOException; +import com.warxim.petep.extension.PetepAPI; +import javafx.fxml.FXMLLoader; +import javafx.scene.layout.AnchorPane; + +/** Configuration pane for configuration of given generic type. */ +@PetepAPI +public abstract class ConfigPane extends AnchorPane { + /** Creates configuration pane from specified template and sets the object as controller. */ + public ConfigPane(String template) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource(template)); + loader.setRoot(this); + loader.setController(this); + loader.load(); + getStylesheets().add("/css/Main.css"); + } + + /** Returns configuration from pane. */ + public abstract C getConfig(); + + /** Sets configuration to pane. */ + public abstract void setConfig(C config); + + /** Checks if configuration is valid. */ + public abstract boolean isValid(); +} diff --git a/src/main/java/com/warxim/petep/gui/component/PduMetadataPane.java b/src/main/java/com/warxim/petep/gui/component/PduMetadataPane.java new file mode 100644 index 0000000..c4d056e --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/component/PduMetadataPane.java @@ -0,0 +1,53 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.component; + +import java.io.IOException; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.proxy.worker.Proxy; +import javafx.fxml.FXMLLoader; +import javafx.scene.layout.AnchorPane; + +/** Configuration pane for PDU meta data configuration. */ +@PetepAPI +public abstract class PduMetadataPane extends AnchorPane { + /** Creates configuration pane from specified template and sets the object as controller. */ + public PduMetadataPane(String template) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource(template)); + loader.setRoot(this); + loader.setController(this); + loader.load(); + getStylesheets().add("/css/Main.css"); + } + + /** Returns configuration from pane. */ + public abstract PDU getPdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size); + + /** Sets configuration to pane. */ + public abstract void setPdu(PDU pdu); + + /** Clears metadata content. */ + public abstract void clear(); +} diff --git a/src/main/java/com/warxim/petep/gui/control/BytesEditor.java b/src/main/java/com/warxim/petep/gui/control/BytesEditor.java new file mode 100644 index 0000000..60f93c0 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/control/BytesEditor.java @@ -0,0 +1,149 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.control; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Optional; +import com.warxim.petep.common.Constant; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.gui.dialog.Dialogs; +import javafx.beans.value.ObservableValue; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.control.Label; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.scene.control.TextInputDialog; +import javafx.scene.layout.AnchorPane; + +/** Byte array editor. */ +@PetepAPI +public class BytesEditor extends AnchorPane { + protected Charset charset; + protected byte[] bytes; + + @FXML + protected TabPane tabs; + + @FXML + protected Label charsetLabel; + + public BytesEditor() throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/control/BytesEditor.fxml")); + loader.setRoot(this); + loader.setController(this); + loader.setClassLoader(getClass().getClassLoader()); + loader.load(); + + charset = Constant.DEFAULT_CHARSET; + + charsetLabel.setText(charset.toString()); + + tabs.getSelectionModel().selectedItemProperty().addListener(this::onTabChange); + + tabs.getTabs().add(new TextEditorTab()); + tabs.getTabs().add(new HexEditorTab()); + } + + protected void onTabChange(ObservableValue observable, Tab oldTab, Tab newTab) { + if (oldTab != null) { + bytes = ((BytesEditorTab) oldTab).getBytes(); + } + + if (bytes == null) { + return; + } + + if (newTab != null) { + ((BytesEditorTab) newTab).setBytes(bytes, bytes.length, charset); + } + } + + public void setData(byte[] bytes, int size, Charset charset) { + this.bytes = bytes; + this.charset = charset; + + BytesEditorTab currentTab = (BytesEditorTab) tabs.getSelectionModel().getSelectedItem(); + if (currentTab != null) { + currentTab.setBytes(bytes, size, charset); + } + + charsetLabel.setText(charset.displayName()); + } + + public void setData(byte[] bytes, Charset charset) { + setData(bytes, bytes.length, charset); + } + + public void setBytes(byte[] bytes, int size) { + this.bytes = bytes; + + BytesEditorTab currentTab = (BytesEditorTab) tabs.getSelectionModel().getSelectedItem(); + if (currentTab != null) { + currentTab.setBytes(bytes, size, charset); + } + } + + public void setBytes(byte[] bytes) { + setBytes(bytes, bytes.length); + } + + public void setCharset(Charset charset) { + BytesEditorTab currentTab = (BytesEditorTab) tabs.getSelectionModel().getSelectedItem(); + if (currentTab != null) { + bytes = currentTab.getBytes(); + } + + this.charset = charset; + + if (currentTab != null) { + currentTab.setBytes(bytes, bytes.length, charset); + } + + charsetLabel.setText(charset.displayName()); + } + + public byte[] getBytes() { + bytes = ((BytesEditorTab) tabs.getSelectionModel().getSelectedItem()).getBytes(); + + return bytes; + } + + public Charset getCharset() { + return charset; + } + + @FXML + protected void onCharsetClick() { + TextInputDialog dialog = new TextInputDialog(charset.toString()); + dialog.setTitle("Change charset"); + dialog.setHeaderText("Change charset"); + dialog.setContentText("New charset:"); + + Optional result = dialog.showAndWait(); + + result.ifPresent((String newCharset) -> { + if (!Charset.isSupported(newCharset)) { + Dialogs.createErrorDialog("Charset not supported", "Specified charset is not supported!"); + return; + } + + setCharset(Charset.forName(newCharset)); + }); + } +} diff --git a/src/main/java/com/warxim/petep/gui/control/BytesEditorTab.java b/src/main/java/com/warxim/petep/gui/control/BytesEditorTab.java new file mode 100644 index 0000000..88907cd --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/control/BytesEditorTab.java @@ -0,0 +1,27 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.control; + +import java.nio.charset.Charset; +import com.warxim.petep.extension.PetepAPI; + +@PetepAPI +public interface BytesEditorTab { + void setBytes(byte[] bytes, int size, Charset charset); + + byte[] getBytes(); +} diff --git a/src/main/java/com/warxim/petep/gui/control/HexEditorTab.java b/src/main/java/com/warxim/petep/gui/control/HexEditorTab.java new file mode 100644 index 0000000..53b11d3 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/control/HexEditorTab.java @@ -0,0 +1,87 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.control; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.regex.Pattern; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.util.BytesUtils; +import javafx.beans.value.ObservableValue; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.control.Tab; +import javafx.scene.control.TextArea; + +@PetepAPI +public class HexEditorTab extends Tab implements BytesEditorTab { + private static final Pattern HEX_FORMAT_PATTERN_1 = Pattern.compile("[^\\s0-9A-F]"); + private static final Pattern HEX_FORMAT_PATTERN_2 = + Pattern.compile("([0-9A-F][0-9A-F])([0-9A-F])"); + private static final Pattern HEX_FORMAT_PATTERN_3 = + Pattern.compile("(^| )([0-9A-F]) ([0-9A-F])($| )"); + private static final Pattern HEX_FORMAT_PATTERN_4 = Pattern.compile("(^| )([0-9A-F])($| )"); + + @FXML + private TextArea textInput; + + public HexEditorTab() throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/control/TextEditorTab.fxml")); + loader.setRoot(this); + loader.setController(this); + loader.setClassLoader(getClass().getClassLoader()); + loader.load(); + + // Automatic formating. + textInput.focusedProperty().addListener(this::onTextFocusChange); + textInput.textProperty().addListener(this::onTextPropertyChange); + + setText("Hex"); + } + + private void onTextFocusChange( + ObservableValue observable, + boolean oldValue, + boolean newValue) { + if (oldValue) { + byte[] bytes = BytesUtils + .stringToBytes(HEX_FORMAT_PATTERN_4.matcher(textInput.getText()).replaceAll("$10$2$3")); + + setBytes(bytes, bytes.length, null); + } + } + + private void onTextPropertyChange( + ObservableValue observable, + String oldValue, + String newValue) { + textInput.setText(HEX_FORMAT_PATTERN_3.matcher(HEX_FORMAT_PATTERN_2 + .matcher(HEX_FORMAT_PATTERN_1.matcher(newValue.toUpperCase()).replaceAll("")) + .replaceAll("$1 $2")).replaceAll("$1$2$3$4").replace(" ", " ")); + } + + @Override + public void setBytes(byte[] bytes, int size, Charset charset) { + textInput.setText(BytesUtils.bytesToString(bytes, size)); + } + + @Override + public byte[] getBytes() { + return BytesUtils + .stringToBytes(HEX_FORMAT_PATTERN_4.matcher(textInput.getText()).replaceAll("$10$2$3")); + } +} diff --git a/src/main/java/com/warxim/petep/gui/control/PduEditor.java b/src/main/java/com/warxim/petep/gui/control/PduEditor.java new file mode 100644 index 0000000..dc10918 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/control/PduEditor.java @@ -0,0 +1,283 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.control; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.DefaultPdu; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.gui.component.PduMetadataPane; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.worker.Interceptor; +import com.warxim.petep.proxy.worker.Proxy; +import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ComboBox; +import javafx.scene.control.ListView; +import javafx.scene.layout.AnchorPane; + +/** PDU editor. */ +@PetepAPI +public class PduEditor extends AnchorPane { + private static final Interceptor nullInterceptor = new Interceptor(0, null, null) { + @Override + public void stop() { + // No action needed. + } + + @Override + public boolean prepare() { + return false; + } + + @Override + public boolean intercept(PDU pdu) { + return false; + } + + @Override + public String toString() { + return "Send out of PETEP"; + } + }; + + @FXML + private ListView tagsList; + + @FXML + private BytesEditor dataInput; + + @FXML + private ComboBox proxyInput; + @FXML + private ComboBox connectionInput; + @FXML + private ComboBox destinationInput; + @FXML + private ComboBox interceptorInput; + + @FXML + private AnchorPane metadataPane; + @FXML + private CheckBox flowInput; + + private ObservableList interceptorsC2S; + private ObservableList interceptorsS2C; + + public PduEditor() throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/control/PduEditor.fxml")); + loader.setRoot(this); + loader.setController(this); + loader.setClassLoader(getClass().getClassLoader()); + loader.load(); + + destinationInput + .setItems(FXCollections.observableArrayList(PduDestination.CLIENT, PduDestination.SERVER)); + + connectionInput.focusedProperty().addListener(this::onConnectionFocusChange); + proxyInput.valueProperty().addListener(this::onProxyChange); + destinationInput.valueProperty().addListener(this::onDestinationChange); + flowInput.selectedProperty().addListener(this::onFlowChange); + + proxyInput.setDisable(true); + destinationInput.setDisable(true); + connectionInput.setDisable(true); + interceptorInput.setDisable(true); + } + + /** Loads selected proxy interface. */ + private void onProxyChange( + ObservableValue observable, + Proxy oldValue, + Proxy newValue) { + if (newValue == null) { + return; + } + + connectionInput.getSelectionModel().clearSelection(); + + if (oldValue == null + || oldValue.getModule().getFactory() != newValue.getModule().getFactory()) { + loadMetadataPane(newValue); + } + } + + /** Reloads connection list when connection box gets focused. */ + private void onConnectionFocusChange( + ObservableValue observable, + boolean oldValue, + boolean newValue) { + if (!newValue) { + return; + } + + Proxy proxy = proxyInput.getSelectionModel().getSelectedItem(); + if (proxy == null) { + return; + } + + connectionInput.setItems(FXCollections.observableList(proxy.getConnectionManager().getList())); + } + + /** Shows/hides flow editor. */ + private void onFlowChange( + ObservableValue observable, + boolean oldValue, + boolean newValue) { + proxyInput.setDisable(oldValue); + destinationInput.setDisable(oldValue); + connectionInput.setDisable(oldValue); + interceptorInput.setDisable(oldValue); + } + + /** Changes interceptor list on destination change. */ + private void onDestinationChange( + ObservableValue observable, + PduDestination oldValue, + PduDestination newValue) { + if (newValue == PduDestination.CLIENT) { + interceptorInput.setItems(interceptorsC2S); + } else { + interceptorInput.setItems(interceptorsS2C); + } + } + + public void init(PetepHelper helper) { + proxyInput.setItems(FXCollections.observableList(helper.getProxies())); + + interceptorsC2S = FXCollections.observableArrayList(helper.getInterceptorsC2S()); + interceptorsC2S.add(nullInterceptor); + + interceptorsS2C = FXCollections.observableArrayList(helper.getInterceptorsS2C()); + interceptorsS2C.add(nullInterceptor); + } + + @FXML + private void onAddTagButtonClick(ActionEvent event) { + String tag = Dialogs.createTextInputDialog("New tag", "New tag: "); + + if (tag != null) { + tagsList.getItems().add(tag); + } + } + + @FXML + private void onRemoveTagButtonClick(ActionEvent event) { + int index = tagsList.getSelectionModel().getSelectedIndex(); + + if (index == -1) { + return; + } + + tagsList.getItems().remove(tagsList.getSelectionModel().getSelectedIndex()); + } + + private void loadMetadataPane(Proxy proxy) { + metadataPane.getChildren().clear(); + + try { + PduMetadataPane pane = proxy.getModule().getFactory().createPduMetadataPane(); + if (pane != null) { + AnchorPane.setLeftAnchor(pane, 0D); + AnchorPane.setRightAnchor(pane, 0D); + + metadataPane.getChildren().add(pane); + } + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during PDU metadata pane creation.", e); + + proxyInput.getSelectionModel().clearSelection(); + } + } + + public PDU getPdu() { + PDU pdu; + + if (!metadataPane.getChildren().isEmpty()) { + PduMetadataPane pane = ((PduMetadataPane) metadataPane.getChildren().get(0)); + pdu = pane.getPdu(proxyInput.getValue(), connectionInput.getValue(), + destinationInput.getValue(), dataInput.getBytes(), dataInput.getBytes().length); + } else { + pdu = new DefaultPdu(proxyInput.getValue(), connectionInput.getValue(), + destinationInput.getValue(), dataInput.getBytes(), dataInput.getBytes().length); + } + + pdu.setCharset(dataInput.getCharset()); + + int interceptorId = interceptorInput.getSelectionModel().getSelectedIndex(); + if (interceptorId != 0) { + pdu.setLastInterceptor(interceptorInput.getItems().get(interceptorId - 1)); + } + + return pdu; + } + + public void setPdu(PDU pdu) { + dataInput.setData(pdu.getBuffer(), pdu.getSize(), pdu.getCharset()); + tagsList.setItems(FXCollections.observableArrayList(pdu.getTags())); + + Proxy proxy = pdu.getProxy(); + + proxyInput.getSelectionModel().select(proxy); + + if (!metadataPane.getChildren().isEmpty()) { + PduMetadataPane pane = ((PduMetadataPane) metadataPane.getChildren().get(0)); + + pane.setPdu(pdu); + } + + destinationInput.getSelectionModel().select(pdu.getDestination()); + + connectionInput.setItems(FXCollections.observableList(proxy.getConnectionManager().getList())); + connectionInput.getSelectionModel().select(pdu.getConnection()); + + if (pdu.getDestination() == PduDestination.CLIENT) { + interceptorInput.setItems(interceptorsC2S); + } else { + interceptorInput.setItems(interceptorsS2C); + } + + if (pdu.getLastInterceptor() == null) { + interceptorInput.getSelectionModel().select(0); + } else { + interceptorInput.getSelectionModel().select(pdu.getLastInterceptor().getId() + 1); + } + } + + public void clear() { + dataInput.setBytes(new byte[0]); + tagsList.getItems().clear(); + proxyInput.getSelectionModel().clearSelection(); + destinationInput.getSelectionModel().clearSelection(); + connectionInput.getSelectionModel().clearSelection(); + + if (!metadataPane.getChildren().isEmpty()) { + PduMetadataPane pane = ((PduMetadataPane) metadataPane.getChildren().get(0)); + pane.clear(); + } + } +} diff --git a/src/main/java/com/warxim/petep/gui/control/TextEditorTab.java b/src/main/java/com/warxim/petep/gui/control/TextEditorTab.java new file mode 100644 index 0000000..08eefee --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/control/TextEditorTab.java @@ -0,0 +1,59 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.control; + +import java.io.IOException; +import java.nio.charset.Charset; +import com.warxim.petep.common.Constant; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.util.GuiUtils; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.control.Tab; +import javafx.scene.control.TextArea; + +@PetepAPI +public class TextEditorTab extends Tab implements BytesEditorTab { + private Charset charset; + + @FXML + private TextArea textInput; + + public TextEditorTab() throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/control/TextEditorTab.fxml")); + loader.setRoot(this); + loader.setController(this); + loader.setClassLoader(getClass().getClassLoader()); + loader.load(); + + charset = Constant.DEFAULT_CHARSET; + + setText("Text"); + } + + @Override + public void setBytes(byte[] bytes, int size, Charset charset) { + this.charset = charset; + + textInput.setText(GuiUtils.formatText(new String(bytes, 0, size, charset))); + } + + @Override + public byte[] getBytes() { + return GuiUtils.unformatText(textInput.getText()).getBytes(charset); + } +} diff --git a/src/main/java/com/warxim/petep/gui/controller/ApplicationController.java b/src/main/java/com/warxim/petep/gui/controller/ApplicationController.java new file mode 100644 index 0000000..f1fdc55 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/controller/ApplicationController.java @@ -0,0 +1,146 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.controller; + +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.Bundle; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.gui.GuiBundle; +import com.warxim.petep.gui.controller.log.LogController; +import com.warxim.petep.gui.controller.settings.SettingsController; +import com.warxim.petep.gui.dialog.AboutDialog; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.gui.dialog.ProjectInfoDialog; +import com.warxim.petep.gui.guide.GuideDialog; +import com.warxim.petep.helper.DefaultGuiHelper; +import com.warxim.petep.util.GuiUtils; +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.Node; +import javafx.scene.control.TabPane; + +/** Application controller. */ +public final class ApplicationController implements Initializable { + /** Main application tabs. */ + @FXML + private TabPane tabs; + + @Override + public void initialize(URL location, ResourceBundle resources) { + // Initialize tabs. + initTabs(); + + // Setup GUI bundle. + GuiBundle.getInstance().setApplicationController(this); + + // Initialize extensions GUI. + Bundle.getInstance() + .getExtensionManager() + .initGui(new DefaultGuiHelper(GuiBundle.getInstance())); + } + + /** Initializes main tabs. */ + private void initTabs() { + registerLogTab(); + registerSettingsTab(); + } + + /** Loads and registers settings tab. */ + private void registerSettingsTab() { + try { + FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/tab/Settings.fxml")); + fxmlLoader.setController(new SettingsController()); + registerTab("Settings", fxmlLoader.load()); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not add settings tab", e); + } + } + + /** Loads and registers log tab. */ + private void registerLogTab() { + try { + FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/tab/Log.fxml")); + fxmlLoader.setController(new LogController()); + registerTab("Log", fxmlLoader.load()); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not add log tab", e); + } + } + + /** Shows application about dialog. */ + @FXML + private void showAbout(ActionEvent e) { + AboutDialog.show(); + } + + /** Shows application guide dialog. */ + @FXML + private void showGuide(ActionEvent event) { + try { + new GuideDialog().show(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not open guide dialog", e); + } + } + + /** Shows project info dialog. */ + @FXML + private void onProjectInfoMenuClick(ActionEvent event) { + try { + new ProjectInfoDialog(Bundle.getInstance().getProject(), + Bundle.getInstance().getExtensionManager().getList()).show(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not open project info dialog", e); + } + } + + /** Exits application dialog. */ + @FXML + private void onExitMenuClick(ActionEvent event) { + Platform.exit(); + } + + /** Saves project dialog. */ + @FXML + private void onSaveMenuClick(ActionEvent event) { + try { + Bundle.getInstance().save(); + + Dialogs.createInfoDialog("Project saved", "Project has been saved!"); + } catch (ConfigurationException e) { + Dialogs.createExceptionDialog("Save fault", "Project could not be saved!", e); + Logger.getGlobal().log(Level.SEVERE, "Exception during save", e); + } + } + + /** Registers new tab to main tabs. */ + public void registerTab(String title, Node node) { + GuiUtils.addTabToTabPane(tabs, title, node); + } + + /** Registers new tab to main tabs. */ + public void unregisterTab(Node node) { + GuiUtils.removeTabFromTabPane(tabs, node); + } +} diff --git a/src/main/java/com/warxim/petep/gui/controller/log/LogController.java b/src/main/java/com/warxim/petep/gui/controller/log/LogController.java new file mode 100644 index 0000000..7d32e04 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/controller/log/LogController.java @@ -0,0 +1,137 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.controller.log; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URL; +import java.util.ResourceBundle; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import javafx.application.Platform; +import javafx.css.PseudoClass; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.ScrollPane; +import javafx.scene.text.Font; +import javafx.scene.text.FontWeight; +import javafx.scene.text.Text; +import javafx.scene.text.TextFlow; + +/** Log tab controller. */ +public final class LogController extends Handler implements Initializable { + /** Maximum number of Text elements in text flow. */ + private static final int LIMIT_LOG_CHILDREN = 150; + + private static final PseudoClass INFO_PSEUDO_CLASS = PseudoClass.getPseudoClass("info"); + private static final PseudoClass SEVERE_PSEUDO_CLASS = PseudoClass.getPseudoClass("severe"); + private static final PseudoClass WARNING_PSEUDO_CLASS = PseudoClass.getPseudoClass("warning"); + private static final PseudoClass FINE_PSEUDO_CLASS = PseudoClass.getPseudoClass("fine"); + private static final PseudoClass CONFIG_PSEUDO_CLASS = PseudoClass.getPseudoClass("config"); + private static final PseudoClass OTHER_PSEUDO_CLASS = PseudoClass.getPseudoClass("other"); + + /** Text flow for logs. */ + @FXML + private TextFlow logFlow; + + /** Scroll pane containing text flow. */ + @FXML + private ScrollPane scrollPane; + + @Override + public void initialize(URL location, ResourceBundle resources) { + Logger.getGlobal().addHandler(this); + } + + @Override + public void publish(LogRecord record) { + Platform.runLater(() -> { + // Level. + Level level = record.getLevel(); + + Text levelText; + + if (level == Level.INFO) { + levelText = new Text("[INFO] "); + levelText.pseudoClassStateChanged(INFO_PSEUDO_CLASS, true); + } else if (level == Level.SEVERE) { + levelText = new Text("[SEVERE] "); + levelText.pseudoClassStateChanged(SEVERE_PSEUDO_CLASS, true); + } else if (level == Level.WARNING) { + levelText = new Text("[WARNING] "); + levelText.pseudoClassStateChanged(WARNING_PSEUDO_CLASS, true); + } else if (level == Level.FINE) { + levelText = new Text("[FINE] "); + levelText.pseudoClassStateChanged(FINE_PSEUDO_CLASS, true); + } else if (level == Level.CONFIG) { + levelText = new Text("[CONFIG] "); + levelText.pseudoClassStateChanged(CONFIG_PSEUDO_CLASS, true); + } else { + levelText = new Text("[OTHER] "); + levelText.pseudoClassStateChanged(OTHER_PSEUDO_CLASS, true); + } + levelText.getStyleClass().add("log-record"); + levelText.setFont(Font.font(null, FontWeight.BOLD, 11)); + + // Message. + Text messageText = new Text(record.getMessage()); + + logFlow.getChildren().add(levelText); + logFlow.getChildren().add(messageText); + + // Exception. + if (record.getThrown() != null) { + StringWriter exception = new StringWriter(); + exception.append(System.lineSeparator()); + exception.append("\tException:"); + exception.append(System.lineSeparator()); + exception.append("\t"); + record.getThrown().printStackTrace(new PrintWriter(exception)); + Text exceptionText = new Text(exception.toString()); + logFlow.getChildren().add(exceptionText); + } + + // Separator. + Text logSeparator = new Text(System.lineSeparator()); + logSeparator.setFont(Font.font(null, FontWeight.NORMAL, 1)); + logSeparator.setLineSpacing(0); + logFlow.getChildren().add(logSeparator); + + // Limit children. + int size = logFlow.getChildren().size(); + if (size > LIMIT_LOG_CHILDREN) { + logFlow.getChildren().remove(0, size - LIMIT_LOG_CHILDREN); + } + + // Scroll down automatically. + scrollPane.layout(); + scrollPane.setVvalue(1D); + }); + } + + @Override + public void flush() { + // No action needed. + } + + @Override + public void close() { + // No action needed. + } +} diff --git a/src/main/java/com/warxim/petep/gui/controller/settings/ModuleSettingsController.java b/src/main/java/com/warxim/petep/gui/controller/settings/ModuleSettingsController.java new file mode 100644 index 0000000..f86e033 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/controller/settings/ModuleSettingsController.java @@ -0,0 +1,197 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.controller.settings; + +import java.io.IOException; +import java.net.URL; +import java.util.Optional; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.gui.dialog.module.EditModuleDialog; +import com.warxim.petep.gui.dialog.module.NewModuleDialog; +import com.warxim.petep.module.Module; +import com.warxim.petep.module.ModuleContainer; +import com.warxim.petep.module.ModuleFactory; +import com.warxim.petep.module.ModuleFactoryManager; +import javafx.beans.property.SimpleStringProperty; +import javafx.collections.FXCollections; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Label; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; + +/** Module settings controller. */ +public final class ModuleSettingsController, F extends ModuleFactory> + implements Initializable { + + // Managers. + private final ModuleFactoryManager factoryManager; + private final ModuleContainer moduleContainer; + + // Title. + private final String title; + + // Table. + @FXML + private TableView moduleTable; + + // Label. + @FXML + private Label titleLabel; + + // Columns. + @FXML + private TableColumn nameColumn; + @FXML + private TableColumn codeColumn; + @FXML + private TableColumn moduleColumn; + @FXML + private TableColumn enabledColumn; + + public ModuleSettingsController( + String title, + ModuleFactoryManager factoryManager, + ModuleContainer moduleContainer) { + this.title = title; + this.factoryManager = factoryManager; + this.moduleContainer = moduleContainer; + } + + @Override + public void initialize(URL location, ResourceBundle resources) { + // Set value factories. + nameColumn.setCellValueFactory(new PropertyValueFactory<>("name")); + codeColumn.setCellValueFactory(new PropertyValueFactory<>("code")); + enabledColumn.setCellValueFactory(new PropertyValueFactory<>("enabled")); + moduleColumn.setCellValueFactory( + cell -> new SimpleStringProperty(cell.getValue().getFactory().getName())); + + // Set items to table. + moduleTable.setItems(FXCollections.observableList(moduleContainer.getList())); + + // Set title. + titleLabel.setText(title); + } + + /** Handles edit module button click. */ + @FXML + private void onEditButtonClick(ActionEvent event) { + M module = moduleTable.getSelectionModel().getSelectedItem(); + + if (module == null) { + return; + } + + try { + EditModuleDialog dialog = + new EditModuleDialog<>(module, factoryManager, moduleContainer); + Optional data = dialog.showAndWait(); + + if (!data.isPresent() || data.get() == null) { + return; + } + + // Remove previous module and add new one. + moduleContainer.replace(module, data.get()); + + refreshTable(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during openning of module dialog", e); + } + } + + /** Handles new module button click. */ + @FXML + private void onNewButtonClick(ActionEvent event) { + try { + NewModuleDialog dialog = new NewModuleDialog<>(factoryManager, moduleContainer); + + Optional data = dialog.showAndWait(); + + if (!data.isPresent() || data.get() == null) { + return; + } + + // Add new module to module container. + moduleContainer.add(data.get()); + + refreshTable(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during openning of module dialog", e); + } + } + + /** Handles remove module button click. */ + @FXML + private void onRemoveButtonClick(ActionEvent event) { + M module = moduleTable.getSelectionModel().getSelectedItem(); + + if (module == null) { + return; + } + + if (!Dialogs.createYesOrNoDialog("Are you sure?", + "Do you really want to remove '" + module.getName() + "' from the project?")) { + return; + } + + // Remove module from module container. + moduleContainer.remove(module); + + refreshTable(); + } + + /** Moves module up. */ + @FXML + private void onMoveUpButtonClick(ActionEvent event) { + int index = moduleTable.getSelectionModel().getSelectedIndex(); + + if (index <= 0) { + return; + } + + moduleContainer.swap(index, index - 1); + + refreshTable(); + } + + /** Moves module down. */ + @FXML + private void onMoveDownButtonClick(ActionEvent event) { + int index = moduleTable.getSelectionModel().getSelectedIndex(); + + if (index == -1 || index == moduleContainer.size() - 1) { + return; + } + + moduleContainer.swap(index, index + 1); + + refreshTable(); + } + + /** Refreshes table items. */ + private void refreshTable() { + // modulesTable.refresh does not work - rows are not clickable. + moduleTable.setItems(FXCollections.observableList(moduleContainer.getList())); + } +} diff --git a/src/main/java/com/warxim/petep/gui/controller/settings/SettingsController.java b/src/main/java/com/warxim/petep/gui/controller/settings/SettingsController.java new file mode 100644 index 0000000..d0f89fa --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/controller/settings/SettingsController.java @@ -0,0 +1,169 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.controller.settings; + +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.Bundle; +import com.warxim.petep.core.PetepState; +import com.warxim.petep.core.listener.PetepListener; +import com.warxim.petep.gui.GuiBundle; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.proxy.factory.ProxyModuleFactory; +import com.warxim.petep.proxy.module.ProxyModule; +import com.warxim.petep.util.GuiUtils; +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.Node; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.TabPane; + +/** Settings controller. */ +public final class SettingsController implements Initializable, PetepListener { + @FXML + private TabPane tabs; + @FXML + private Label statusLabel; + @FXML + private Button startStopButton; + + @Override + public void initialize(URL location, ResourceBundle resources) { + // Register settings controller to GUI bundle. + GuiBundle.getInstance().setSettingsController(this); + + // Load proxy settings tab. + loadProxySettings(); + loadInterceptorC2SSettings(); + loadInterceptorS2CSettings(); + + // Register PETEP listener. + Bundle.getInstance().getPetepListenerManager().registerListener(this); + } + + /** Registers new tab to settings tab. */ + public void registerTab(String title, Node node) { + GuiUtils.addTabToTabPane(tabs, title, node); + } + + /** Unregisters tab from settings tab. */ + public void unregisterTab(Node node) { + GuiUtils.removeTabFromTabPane(tabs, node); + } + + private void loadProxySettings() { + try { + FXMLLoader fxmlLoader = + new FXMLLoader(getClass().getResource("/fxml/tab/settings/ModuleSettings.fxml")); + + fxmlLoader.setController(new ModuleSettingsController( + "Proxies", Bundle.getInstance().getProxyModuleFactoryManager(), + Bundle.getInstance().getProxyModuleContainer())); + + registerTab("Proxies", fxmlLoader.load()); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not add proxies tab", e); + } + } + + private void loadInterceptorC2SSettings() { + try { + FXMLLoader fxmlLoader = + new FXMLLoader(getClass().getResource("/fxml/tab/settings/ModuleSettings.fxml")); + + fxmlLoader + .setController(new ModuleSettingsController( + "Interceptors C2S (client → server)", + Bundle.getInstance().getInterceptorModuleFactoryManager(), + Bundle.getInstance().getInterceptorModuleContainerC2S())); + + registerTab("Interceptors C2S", fxmlLoader.load()); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not add interceptors C2S tab", e); + } + } + + private void loadInterceptorS2CSettings() { + try { + FXMLLoader fxmlLoader = + new FXMLLoader(getClass().getResource("/fxml/tab/settings/ModuleSettings.fxml")); + + fxmlLoader + .setController(new ModuleSettingsController( + "Interceptors S2C (server → client)", + Bundle.getInstance().getInterceptorModuleFactoryManager(), + Bundle.getInstance().getInterceptorModuleContainerS2C())); + + registerTab("Interceptors S2C", fxmlLoader.load()); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not add interceptors S2C tab", e); + } + } + + @FXML + private void onStartStopButtonClick(ActionEvent e) { + if (Bundle.getInstance().getPetepManager().getState() == PetepState.STOPPED) { + // Lock GUI + lock(); + Platform.runLater(() -> statusLabel.setText("STARTING...")); + startStopButton.setText("STOP"); + + Bundle.getInstance().getPetepManager().start(); + } else { + Bundle.getInstance().getPetepManager().stop(); + } + } + + /** Locks settings. */ + private void lock() { + this.tabs.setDisable(true); + } + + /** Unlocks settings. */ + private void unlock() { + this.tabs.setDisable(false); + } + + @Override + public void afterStart(PetepHelper helper) { + Platform.runLater(() -> statusLabel.setText("STARTED")); + } + + @Override + public void afterStop(PetepHelper helper) { + // Unlock GUI + Platform.runLater(() -> { + unlock(); + statusLabel.setText("STOPPED"); + startStopButton.setText("START"); + }); + } + + @Override + public void afterPrepare(PetepHelper helper) { + Platform.runLater(() -> statusLabel.setText("PREPARED")); + } +} diff --git a/src/main/java/com/warxim/petep/gui/dialog/AboutDialog.java b/src/main/java/com/warxim/petep/gui/dialog/AboutDialog.java new file mode 100644 index 0000000..6668f58 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/dialog/AboutDialog.java @@ -0,0 +1,106 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.dialog; + +import java.awt.Desktop; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.common.Constant; +import com.warxim.petep.gui.GuiBundle; +import javafx.event.ActionEvent; +import javafx.geometry.Insets; +import javafx.scene.control.Alert; +import javafx.scene.control.Hyperlink; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.GridPane; +import javafx.stage.Stage; + +/** About dialog. */ +public final class AboutDialog { + private AboutDialog() {} + + /** Shows about dialog. */ + public static void show() { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + + alert.setTitle("About PETEP"); + alert.setHeaderText("PETEP v" + Constant.VERSION); + + Image icon = GuiBundle.getInstance().getPetepIcon(); + + ImageView image = new ImageView(icon); + image.setFitWidth(50); + image.setFitHeight(50); + alert.setGraphic(image); + + ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().add(icon); + + // Info + Label infoLabel = + new Label("PETEP is a tool for penetration testing of network communication (TCP, ...)."); + + // Version + Label versionLabel = new Label("Version:"); + versionLabel.getStyleClass().add("input-label"); + Label versionValueLabel = new Label(Constant.VERSION); + + // Link + Label linkLabel = new Label("Website: "); + linkLabel.getStyleClass().add("input-label"); + Hyperlink link = new Hyperlink(Constant.WEB); + link.setOnAction((ActionEvent event) -> { + try { + Desktop.getDesktop().browse(new URI(Constant.WEB)); + } catch (IOException | URISyntaxException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not open PETEP link."); + } + }); + + // Copyright + Label copyrightLabel = new Label("Copyright (C) Michal Válka, 2020, all rights reserved."); + + // Grid + GridPane grid = new GridPane(); + grid.setMaxWidth(Double.MAX_VALUE); + grid.setHgap(10); + grid.setVgap(10); + grid.setPadding(new Insets(20, 150, 10, 10)); + + // Info + grid.add(infoLabel, 0, 0, 2, 1); + + // Version + grid.add(versionLabel, 0, 1); + grid.add(versionValueLabel, 1, 1); + + // Link + grid.add(linkLabel, 0, 2); + grid.add(link, 1, 2); + + // Copyright + grid.add(copyrightLabel, 0, 3, 2, 1); + + alert.getDialogPane().setContent(grid); + + alert.showAndWait(); + } +} diff --git a/src/main/java/com/warxim/petep/gui/dialog/Dialogs.java b/src/main/java/com/warxim/petep/gui/dialog/Dialogs.java new file mode 100644 index 0000000..e3e31df --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/dialog/Dialogs.java @@ -0,0 +1,268 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.dialog; + +import java.awt.Desktop; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Optional; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.common.Constant; +import com.warxim.petep.extension.PetepAPI; +import javafx.event.ActionEvent; +import javafx.geometry.Insets; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Dialog; +import javafx.scene.control.Hyperlink; +import javafx.scene.control.Label; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; +import javafx.scene.control.TextInputDialog; +import javafx.scene.image.Image; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.Priority; +import javafx.stage.Stage; +import javafx.util.Pair; + +/** Dialog helper. */ +@PetepAPI +public final class Dialogs { + private static Image defaultIcon; + + private Dialogs() {} + + public static void setDefaultIcon(Image icon) { + defaultIcon = icon; + } + + public static Image getDefaultIcon() { + return defaultIcon; + } + + /** Creates simple error dialog. */ + public static void createErrorDialog(String title, String message) { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle(title); + alert.setHeaderText(title); + alert.setContentText(message); + ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon); + alert.showAndWait(); + } + + /** Creates simple success dialog. */ + public static void createInfoDialog(String title, String message) { + Alert alert = new Alert(AlertType.INFORMATION); + alert.setTitle(title); + alert.setHeaderText(title); + alert.setContentText(message); + ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon); + alert.showAndWait(); + } + + /** Creates simple exception dialog. */ + public static void createExceptionDialog(String title, String message, Exception exception) { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle(title); + alert.setHeaderText(title); + alert.setContentText(message); + + ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + exception.printStackTrace(pw); + String exceptionText = sw.toString(); + + TextArea textArea = new TextArea(exceptionText); + textArea.setEditable(false); + textArea.setWrapText(true); + + textArea.setMaxWidth(Double.MAX_VALUE); + textArea.setMaxHeight(Double.MAX_VALUE); + GridPane.setVgrow(textArea, Priority.ALWAYS); + GridPane.setHgrow(textArea, Priority.ALWAYS); + + Label label = new Label("The exception stacktrace was:"); + + GridPane expContent = new GridPane(); + expContent.setMaxWidth(Double.MAX_VALUE); + expContent.add(label, 0, 0); + expContent.add(textArea, 0, 1); + + alert.getDialogPane().setExpandableContent(expContent); + + alert.showAndWait(); + } + + /** Creates simple yes / no dialog. */ + public static boolean createYesOrNoDialog(String title, String message) { + Alert alert = new Alert(AlertType.CONFIRMATION, message, ButtonType.YES, ButtonType.NO, + ButtonType.CANCEL); + alert.setTitle(title); + alert.setHeaderText(title); + ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon); + + alert.showAndWait(); + + return alert.getResult() == ButtonType.YES; + } + + /** Creates simple text input dialog. */ + public static String createTextInputDialog(String title, String message) { + return createTextInputDialog(title, message, ""); + } + + /** Creates simple text input dialog. */ + public static String createTextInputDialog(String title, String message, String value) { + TextInputDialog dialog = new TextInputDialog(value); + dialog.setTitle(title); + dialog.setHeaderText(title); + dialog.setContentText(message); + + ((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon); + + Optional result = dialog.showAndWait(); + if (result.isPresent()) { + return result.get(); + } + + return null; + } + + /** Creates dialog for text pair input. */ + public static Pair createTextPairDialog( + String title, + String firstLabel, + String secondLabel) { + return createTextPairDialog(title, firstLabel, secondLabel, "", ""); + } + + /** Creates dialog for text pair input with default values. */ + public static Pair createTextPairDialog( + String title, + String firstLabel, + String secondLabel, + String firstValue, + String secondValue) { + Dialog> dialog = new Dialog<>(); + dialog.setTitle(title); + dialog.setHeaderText(title); + + ((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon); + + dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); + + Label keyLabel = new Label(firstLabel); + TextField keyInput = new TextField(firstValue); + keyInput.setMaxWidth(Double.MAX_VALUE); + + Label valueLabel = new Label(secondLabel); + TextField valueInput = new TextField(secondValue); + valueInput.setMaxWidth(Double.MAX_VALUE); + + GridPane grid = new GridPane(); + grid.setMaxWidth(Double.MAX_VALUE); + grid.setHgap(10); + grid.setVgap(10); + grid.setPadding(new Insets(20, 150, 10, 10)); + + grid.add(keyLabel, 0, 0); + grid.add(keyInput, 1, 0); + GridPane.setHgrow(keyInput, Priority.ALWAYS); + + grid.add(valueLabel, 0, 1); + grid.add(valueInput, 1, 1); + GridPane.setHgrow(valueInput, Priority.ALWAYS); + + dialog.getDialogPane().setContent(grid); + + dialog.setResultConverter((ButtonType buttonType) -> { + if (buttonType == ButtonType.OK) { + return new Pair<>(keyInput.getText(), valueInput.getText()); + } + + return null; + }); + + Optional> result = dialog.showAndWait(); + if (result.isPresent()) { + return result.get(); + } + + return null; + } + + + /** Creates simple new version dialog. */ + public static void createNewVersionDialog(String newVersion) { + Alert alert = new Alert(AlertType.INFORMATION); + alert.setTitle("New version available"); + alert.setHeaderText("New version available"); + ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon); + + // Current Version + Label currentVersionLabel = new Label("Current Version: "); + currentVersionLabel.getStyleClass().add("input-label"); + Label currentVersionValueLabel = new Label(Constant.VERSION); + + // New Version + Label newVersionLabel = new Label("New Version: "); + newVersionLabel.getStyleClass().add("input-label"); + Label newVersionValueLabel = new Label(newVersion); + + // Link + Label linkLabel = new Label("Link: "); + linkLabel.getStyleClass().add("input-label"); + Hyperlink link = new Hyperlink(Constant.WEB); + link.setOnAction((ActionEvent event) -> { + try { + Desktop.getDesktop().browse(new URI(Constant.WEB)); + } catch (IOException | URISyntaxException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not open PETEP link."); + } + }); + + // Grid + GridPane grid = new GridPane(); + grid.setMaxWidth(Double.MAX_VALUE); + grid.setHgap(10); + grid.setVgap(10); + grid.setPadding(new Insets(20, 150, 10, 10)); + + // Current version + grid.add(currentVersionLabel, 0, 0); + grid.add(currentVersionValueLabel, 1, 0); + + // New version + grid.add(newVersionLabel, 0, 1); + grid.add(newVersionValueLabel, 1, 1); + + // Link + grid.add(linkLabel, 0, 2); + grid.add(link, 1, 2); + + alert.getDialogPane().setContent(grid); + + alert.showAndWait(); + } +} diff --git a/src/main/java/com/warxim/petep/gui/dialog/ProjectInfoDialog.java b/src/main/java/com/warxim/petep/gui/dialog/ProjectInfoDialog.java new file mode 100644 index 0000000..821a99c --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/dialog/ProjectInfoDialog.java @@ -0,0 +1,58 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.dialog; + +import java.io.IOException; +import java.util.List; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.project.Project; +import javafx.collections.FXCollections; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; + +/** Project info dialog. */ +public final class ProjectInfoDialog extends SimpleInfoDialog { + // Labels. + @FXML + private Label nameLabel; + @FXML + private Label descriptionLabel; + + // Table. + @FXML + private TableView extensionsTable; + + /** Project info dialog constructor. */ + public ProjectInfoDialog(Project project, List extensions) throws IOException { + super("/fxml/dialog/ProjectInfo.fxml", "Project '" + project.getName() + "'"); + + nameLabel.setText(project.getName()); + descriptionLabel.setText(project.getDescription()); + + // Create cell value factories for extensions. + for (TableColumn col : extensionsTable.getColumns()) { + col.setCellValueFactory(new PropertyValueFactory<>( + col.getId().substring(0, col.getId().length() - "Column".length()))); + } + + // Add extensions to extensions table. + extensionsTable.setItems(FXCollections.observableList(extensions)); + } +} diff --git a/src/main/java/com/warxim/petep/gui/dialog/SimpleInfoDialog.java b/src/main/java/com/warxim/petep/gui/dialog/SimpleInfoDialog.java new file mode 100644 index 0000000..7a48217 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/dialog/SimpleInfoDialog.java @@ -0,0 +1,49 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.dialog; + +import java.io.IOException; +import com.warxim.petep.gui.GuiBundle; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.control.ScrollPane; +import javafx.stage.Stage; + +/** Simple dialog class for creation of custom dialogs. */ +public abstract class SimpleInfoDialog extends Stage { + /** Creates simple info dialog from specified template. */ + public SimpleInfoDialog(String template, String title) throws IOException { + setTitle(title); + setResizable(true); + + // Load template. + FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(template)); + fxmlLoader.setController(this); + ScrollPane root = new ScrollPane(fxmlLoader.load()); + + root.setFitToHeight(true); + root.setFitToWidth(true); + + Scene dialogScene = new Scene(root); + dialogScene.getStylesheets().add("/css/Main.css"); + root.getStyleClass().add("simple-dialog"); + setScene(dialogScene); + + // Set icon. + getIcons().add(GuiBundle.getInstance().getPetepIcon()); + } +} diff --git a/src/main/java/com/warxim/petep/gui/dialog/SimpleInputDialog.java b/src/main/java/com/warxim/petep/gui/dialog/SimpleInputDialog.java new file mode 100644 index 0000000..d7d56a7 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/dialog/SimpleInputDialog.java @@ -0,0 +1,87 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.dialog; + +import java.io.IOException; +import com.warxim.petep.gui.GuiBundle; +import javafx.event.ActionEvent; +import javafx.fxml.FXMLLoader; +import javafx.scene.control.ButtonBar.ButtonData; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Dialog; +import javafx.scene.control.DialogPane; +import javafx.scene.control.ScrollPane; +import javafx.stage.Stage; + +/** Simple dialog class for creation of custom dialogs. */ +public abstract class SimpleInputDialog extends Dialog { + /** Creates simple input dialog from specified template. */ + public SimpleInputDialog(String template, String title, String okText) throws IOException { + setTitle(title); + setResizable(true); + + // Load template. + FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(template)); + fxmlLoader.setController(this); + ScrollPane root = new ScrollPane(fxmlLoader.load()); + + root.setFitToHeight(true); + root.setFitToWidth(true); + + DialogPane dialogPane = getDialogPane(); + dialogPane.getStylesheets().add("/css/Main.css"); + dialogPane.getStyleClass().add("simple-dialog"); + dialogPane.setContent(root); + + // Set icon. + ((Stage) dialogPane.getScene().getWindow()).getIcons() + .add(GuiBundle.getInstance().getPetepIcon()); + + // Create buttons. + ButtonType saveButtonType = new ButtonType(okText, ButtonData.OK_DONE); + dialogPane.getButtonTypes().addAll(ButtonType.CANCEL, saveButtonType); + + // Create bindings. + dialogPane.lookupButton(saveButtonType) + .addEventFilter(ActionEvent.ACTION, this::onOkButtonClick); + + setResultConverter(this::convertResult); + } + + /** Returns result of obtainResult if user has not clicked on cancel. Returns null otherwise. */ + private T convertResult(ButtonType buttonType) { + if (buttonType == ButtonType.CANCEL) { + return null; + } + return this.obtainResult(); + } + + /** Handles save button click. */ + protected void onOkButtonClick(ActionEvent ae) { + if (isValid()) { + return; + } + + ae.consume(); + } + + /** Returns result. */ + protected abstract T obtainResult(); + + /** Checks validity of inputs. */ + protected abstract boolean isValid(); +} diff --git a/src/main/java/com/warxim/petep/gui/dialog/module/EditModuleDialog.java b/src/main/java/com/warxim/petep/gui/dialog/module/EditModuleDialog.java new file mode 100644 index 0000000..6807082 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/dialog/module/EditModuleDialog.java @@ -0,0 +1,126 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.dialog.module; + +import java.io.IOException; +import java.lang.reflect.Type; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.module.Module; +import com.warxim.petep.module.ModuleContainer; +import com.warxim.petep.module.ModuleFactory; +import com.warxim.petep.module.ModuleFactoryManager; +import com.warxim.petep.persistence.Configurable; +import com.warxim.petep.persistence.Storable; +import com.warxim.petep.util.ExtensionUtils; + +/** Edit module dialog. */ +public final class EditModuleDialog, F extends ModuleFactory> + extends ModuleDialog { + private final M oldModule; + + /** Create edit module dialog for specified module. */ + public EditModuleDialog( + M module, + ModuleFactoryManager factoryManager, + ModuleContainer moduleContainer) throws IOException { + super("Edit module", "Save", factoryManager, moduleContainer); + + this.oldModule = module; + + // Select module and disable combo box. + factoryComboBox.getSelectionModel().select(module.getFactory()); + factoryComboBox.setDisable(true); + + // Fill input fields. + codeInput.setText(module.getCode()); + nameInput.setText(module.getName()); + descriptionInput.setText(module.getDescription()); + enabledCheckBox.setSelected(module.isEnabled()); + + // Load config pane. + var pane = createConfigPane(); + if (pane == null) { + return; + } + setConfigPane(pane); + + // Get configuration from module. + var config = ((Configurable) module).saveConfig(); + if (config == null) { + return; + } + + // Set config to pane. + pane.setConfig(config); + } + + @Override + protected M obtainResult() { + M module = super.obtainResult(); + + processStore(module); + processConfig(module); + + return module; + } + + @SuppressWarnings("unchecked") + private void processStore(M module) { + Type storeType = ExtensionUtils.getStoreType(module); + + if (storeType != null) { + if (((Storable) oldModule).saveStore() == null) { + return; + } + + ((Storable) module).loadStore(((Storable) oldModule).saveStore()); + } + } + + @SuppressWarnings("unchecked") + private void processConfig(M module) { + Type configType = ExtensionUtils.getConfigType(module); + + if (configType != null) { + if (((Configurable) module).saveConfig() != null) { + return; + } + + if (((Configurable) oldModule).saveConfig() == null) { + return; + } + + ((Configurable) module).loadConfig(((Configurable) oldModule).saveConfig()); + } + } + + @Override + protected boolean isValid() { + if (!super.isValid()) { + return false; + } + + M result = moduleContainer.get(codeInput.getText()); + if (result != null && !result.equals(oldModule)) { + Dialogs.createErrorDialog("Code reserved", + "You have entered code that is reserved by other module."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/gui/dialog/module/ModuleDialog.java b/src/main/java/com/warxim/petep/gui/dialog/module/ModuleDialog.java new file mode 100644 index 0000000..2bea6f7 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/dialog/module/ModuleDialog.java @@ -0,0 +1,194 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.dialog.module; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.gui.component.ConfigPane; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.gui.dialog.SimpleInputDialog; +import com.warxim.petep.module.Module; +import com.warxim.petep.module.ModuleContainer; +import com.warxim.petep.module.ModuleFactory; +import com.warxim.petep.module.ModuleFactoryManager; +import com.warxim.petep.persistence.Configurable; +import com.warxim.petep.persistence.Configurator; +import com.warxim.petep.util.ExtensionUtils; +import javafx.collections.FXCollections; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ComboBox; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; +import javafx.scene.layout.AnchorPane; +import javafx.util.StringConverter; + +/** Superclass for module dialogs. */ +public abstract class ModuleDialog, F extends ModuleFactory> + extends SimpleInputDialog { + // Managers. + protected final ModuleFactoryManager factoryManager; + protected final ModuleContainer moduleContainer; + + // Inputs. + @FXML + protected ComboBox factoryComboBox; + + @FXML + protected TextField codeInput; + @FXML + protected TextField nameInput; + @FXML + protected TextArea descriptionInput; + @FXML + protected CheckBox enabledCheckBox; + + // Configuration pane. + @FXML + protected AnchorPane factoryPane; + + public ModuleDialog( + String title, + String okText, + ModuleFactoryManager factoryManager, + ModuleContainer moduleContainer) throws IOException { + super("/fxml/tab/settings/ModuleDialog.fxml", title, okText); + + this.factoryManager = factoryManager; + this.moduleContainer = moduleContainer; + + // Create converter to display factory name instead of toString(). + factoryComboBox.setConverter(new StringConverter() { + @Override + public String toString(F factory) { + return factory == null ? "" : factory.getName(); + } + + @Override + public F fromString(String str) { + return null; + } + }); + + // Add available factories to ComboBox. + factoryComboBox.setItems(FXCollections.observableList(factoryManager.getList())); + } + + protected final void setConfigPane(ConfigPane pane) { + if (pane == null) { + // Clear factory pane if config pane does not exist. + factoryPane.getChildren().clear(); + return; + } + + AnchorPane.setLeftAnchor(pane, 0D); + AnchorPane.setRightAnchor(pane, 0D); + + // Add config pane to factory pane. + factoryPane.getChildren().setAll(pane); + } + + protected final ConfigPane createConfigPane() { + // Get selected factory. + F factory = factoryComboBox.getValue(); + + // Determine configuration type using annotations. + Type configType = ExtensionUtils.getConfiguratorType(factory); + if (configType == null) { + return null; + } + + try { + // Create configuration pane using factory. + @SuppressWarnings("unchecked") + var configPane = ((Configurator) factory).createConfigPane(); + + // Return created configuration pane. + return configPane; + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during openning of module dialog", e); + } + + // Return null if it was not possible to create config pane. + return null; + } + + /** Validates inputs. */ + @Override + protected boolean isValid() { + // Validate code. + if (!codeInput.getText().matches("^[a-zA-Z0-9-_.]+$")) { + Dialogs.createErrorDialog("Code required", + "You have to enter code (allowed characters are A-Za-z0-9-_.)."); + return false; + } + + // Validate name. + if (nameInput.getText().isBlank()) { + Dialogs.createErrorDialog("Name required", "You have to enter name."); + return false; + } + + // Validate module factory. + F module = factoryComboBox.getSelectionModel().getSelectedItem(); + if (module == null) { + Dialogs.createErrorDialog("Module type required", "You have to select module type."); + return false; + } + + // Validate configuration pane. + return factoryPane.getChildren().isEmpty() + || ((ConfigPane) factoryPane.getChildren().get(0)).isValid(); + } + + /** Obtains new module from dialog. */ + @Override + protected M obtainResult() { + // Get selected module. + F factory = factoryComboBox.getSelectionModel().getSelectedItem(); + + // Use factory to create module. + M module = factory.createModule(codeInput.getText(), nameInput.getText(), + descriptionInput.getText(), enabledCheckBox.isSelected()); + + // Process config pane. + processConfigPane(module); + + return module; + } + + /** Loads configuration pane on factory change. */ + @FXML + private final void onModuleChange(ActionEvent event) { + setConfigPane(createConfigPane()); + } + + /** Processes configuration. */ + @SuppressWarnings("unchecked") + private void processConfigPane(M module) { + if (!factoryPane.getChildren().isEmpty()) { + // Get factory config pane. + ConfigPane configurator = (ConfigPane) factoryPane.getChildren().get(0); + + // Load config to module. + ((Configurable) module).loadConfig(configurator.getConfig()); + } + } +} diff --git a/src/main/java/com/warxim/petep/gui/dialog/module/NewModuleDialog.java b/src/main/java/com/warxim/petep/gui/dialog/module/NewModuleDialog.java new file mode 100644 index 0000000..ac6ef65 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/dialog/module/NewModuleDialog.java @@ -0,0 +1,49 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.dialog.module; + +import java.io.IOException; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.module.Module; +import com.warxim.petep.module.ModuleContainer; +import com.warxim.petep.module.ModuleFactory; +import com.warxim.petep.module.ModuleFactoryManager; + +/** New module dialog. */ +public final class NewModuleDialog, F extends ModuleFactory> + extends ModuleDialog { + public NewModuleDialog(ModuleFactoryManager factoryManager, ModuleContainer moduleContainer) + throws IOException { + super("New module", "Save", factoryManager, moduleContainer); + } + + @Override + protected boolean isValid() { + if (!super.isValid()) { + return false; + } + + // Determine whether the code is already in use. + if (moduleContainer.contains(codeInput.getText())) { + Dialogs.createErrorDialog("Code reserved", + "You have entered code that is reserved by other module."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/gui/guide/Guide.java b/src/main/java/com/warxim/petep/gui/guide/Guide.java new file mode 100644 index 0000000..5e35614 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/guide/Guide.java @@ -0,0 +1,49 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.guide; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import com.warxim.petep.extension.PetepAPI; + +/** + * Guide base class. (Guides are HTML pages that contain various tutorials, tips and tricks for + * extension modules and also PETEP core.) + */ +@PetepAPI +public abstract class Guide { + public Guide() {} + + public abstract String getTitle(); + + public abstract String getHtml(); + + /** Returns content of HTML file from resource path. */ + protected String loadHtmlResource(String path) { + try (InputStream in = getClass().getResourceAsStream(path)) { + return new String(in.readAllBytes(), StandardCharsets.UTF_8); + } catch (IOException e) { + return "

Could not load " + getTitle() + " Guide:

" + e.getMessage() + "

"; + } + } + + /** Returns text displayed in list view in guide dialog. */ + public String toString() { + return getTitle(); + } +} diff --git a/src/main/java/com/warxim/petep/gui/guide/GuideDialog.java b/src/main/java/com/warxim/petep/gui/guide/GuideDialog.java new file mode 100644 index 0000000..70403aa --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/guide/GuideDialog.java @@ -0,0 +1,93 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.guide; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.gui.GuiBundle; +import com.warxim.petep.gui.dialog.SimpleInfoDialog; +import com.warxim.petep.util.WebUtils; +import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; +import javafx.concurrent.Worker; +import javafx.concurrent.Worker.State; +import javafx.fxml.FXML; +import javafx.scene.control.ListView; +import javafx.scene.web.WebEngine; +import javafx.scene.web.WebView; +import netscape.javascript.JSObject; + +/** + * Guide dialog contains list view of all guides and handles their rendering using WebView + * component. + */ +public final class GuideDialog extends SimpleInfoDialog { + @FXML + private ListView guideList; + @FXML + private WebView webView; + + public GuideDialog() throws IOException { + super("/fxml/guide/GuideDialog.fxml", "Guide"); + + WebEngine webEngine = webView.getEngine(); + + // Initialize list of guides. + guideList.setItems( + FXCollections.observableList(GuiBundle.getInstance().getGuideManager().getList())); + + // Run loadGuide(title, html) when Guide gets selected. + guideList.getSelectionModel().selectedItemProperty().addListener(this::hangleGuideChange); + + webEngine.getLoadWorker().stateProperty().addListener(this::stateListener); + + // Load HTML template. + try { + webEngine.load(getClass().getResource("/html/guide/Guide.html").toURI().toURL().toString()); + } catch (URISyntaxException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not load guide dialog!", e); + return; + } + + // Enable JavaScript. + webEngine.setJavaScriptEnabled(true); + } + + /** Runs loadGuide(title, html) when Guide gets selected. */ + private void hangleGuideChange( + ObservableValue observable, + Guide oldValue, + Guide newValue) { + webView.getEngine() + .executeScript("loadGuide(" + WebUtils.toJavaScriptParam(newValue.getTitle()) + ", " + + WebUtils.toJavaScriptParam(newValue.getHtml()) + ")"); + } + + /** Registers guide utils to JavaScript. */ + private void stateListener( + ObservableValue observable, + Worker.State oldValue, + Worker.State newValue) { + if (newValue == State.SUCCEEDED) { + guideList.getSelectionModel().selectFirst(); + JSObject win = (JSObject) webView.getEngine().executeScript("window"); + win.setMember("petep", new GuideJS()); + } + } +} diff --git a/src/main/java/com/warxim/petep/gui/guide/GuideJS.java b/src/main/java/com/warxim/petep/gui/guide/GuideJS.java new file mode 100644 index 0000000..a8f9472 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/guide/GuideJS.java @@ -0,0 +1,36 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.guide; + +import java.awt.Desktop; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** GuideJS is API for JavaScript that allows it to use useful Java functions. */ +public final class GuideJS { + /** Opens link in default desktop web browser. */ + public void openLink(String url) { + try { + Desktop.getDesktop().browse(new URI(url)); + } catch (IOException | URISyntaxException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not open URL: " + url); + } + } +} diff --git a/src/main/java/com/warxim/petep/gui/guide/GuideManager.java b/src/main/java/com/warxim/petep/gui/guide/GuideManager.java new file mode 100644 index 0000000..75e02ff --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/guide/GuideManager.java @@ -0,0 +1,54 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.guide; + +import java.util.ArrayList; +import java.util.List; +import com.warxim.petep.gui.guide.internal.BasicsGuide; +import com.warxim.petep.gui.guide.internal.DiagramGuide; +import com.warxim.petep.gui.guide.internal.IntroductionGuide; +import com.warxim.petep.gui.guide.internal.TipsAndTricksGuide; + +/** Manages guides. */ +public final class GuideManager { + private final List guides; + + public GuideManager() { + guides = new ArrayList<>(); + + // Load internal guides. + add(new IntroductionGuide()); + add(new BasicsGuide()); + add(new TipsAndTricksGuide()); + add(new DiagramGuide()); + } + + /** Adds guide to the manager. */ + public synchronized boolean add(Guide guide) { + return guides.add(guide); + } + + /** Removes guide from the manager. */ + public synchronized boolean remove(Guide guide) { + return guides.remove(guide); + } + + /** Returns list of guides. */ + public List getList() { + return guides; + } +} diff --git a/src/main/java/com/warxim/petep/gui/guide/internal/BasicsGuide.java b/src/main/java/com/warxim/petep/gui/guide/internal/BasicsGuide.java new file mode 100644 index 0000000..c398be1 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/guide/internal/BasicsGuide.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.guide.internal; + +import com.warxim.petep.gui.guide.Guide; + +/** Introduction to PETEP. */ +public final class BasicsGuide extends Guide { + @Override + public String getTitle() { + return "Basics"; + } + + @Override + public String getHtml() { + return loadHtmlResource("/html/guide/internal/BasicsGuide.html"); + } +} diff --git a/src/main/java/com/warxim/petep/gui/guide/internal/DiagramGuide.java b/src/main/java/com/warxim/petep/gui/guide/internal/DiagramGuide.java new file mode 100644 index 0000000..1b9951b --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/guide/internal/DiagramGuide.java @@ -0,0 +1,108 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.guide.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.StringJoiner; +import com.warxim.petep.Bundle; +import com.warxim.petep.gui.guide.Guide; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.proxy.module.ProxyModule; +import com.warxim.petep.util.WebUtils; + +/** Diagram guide renders diagram of PETEP. */ +public final class DiagramGuide extends Guide { + @Override + public String getTitle() { + return "Diagram"; + } + + @Override + public String getHtml() { + // Load templates. + String page = loadHtmlResource("/html/guide/internal/diagram/Diagram.html"); + String interceptorTemplate = + loadHtmlResource("/html/guide/internal/diagram/DiagramInterceptor.html"); + + // Generate interceptors. + page = page.replace("{{interceptorsC2S}}", generateInterceptors( + Bundle.getInstance().getInterceptorModuleContainerC2S().getList(), interceptorTemplate, + loadHtmlResource("/html/guide/internal/diagram/DiagramInterceptorSeparatorRight.html"))); + + page = page.replace("{{interceptorsS2C}}", + generateInterceptors( + reverseList(Bundle.getInstance().getInterceptorModuleContainerS2C().getList()), + interceptorTemplate, + loadHtmlResource("/html/guide/internal/diagram/DiagramInterceptorSeparatorLeft.html"))); + + // Generate proxies. + page = page.replace("{{proxies}}", + generateProxies(Bundle.getInstance().getProxyModuleContainer().getList(), + loadHtmlResource("/html/guide/internal/diagram/DiagramProxy.html"))); + + return page; + } + + /** Generates interceptors HTML using specified template separated by specified separator. */ + private static String generateInterceptors( + List modules, + String template, + String separator) { + StringJoiner joiner = new StringJoiner(separator); + + for (InterceptorModule module : modules) { + if (!module.isEnabled()) { + continue; + } + + joiner.add(template.replace("{{name}}", WebUtils.escapeHtml(module.getName())) + .replace("{{code}}", WebUtils.escapeHtml(module.getCode())) + .replace("{{description}}", WebUtils.escapeHtml(module.getDescription()))); + } + + return joiner.toString(); + } + + /** Generates proxies HTML using specified template. */ + private static String generateProxies(List modules, String template) { + StringBuilder builder = new StringBuilder(); + + for (ProxyModule module : modules) { + if (!module.isEnabled()) { + continue; + } + + builder.append(template.replace("{{name}}", WebUtils.escapeHtml(module.getName())) + .replace("{{code}}", WebUtils.escapeHtml(module.getCode())) + .replace("{{description}}", + WebUtils.escapeHtml(module.getDescription()).replace("\n", "
"))); + } + + return builder.toString(); + } + + /** Returns reversed list. */ + private static List reverseList(List alist) { + ArrayList rlist = new ArrayList<>(alist); + + Collections.reverse(rlist); + + return rlist; + } +} diff --git a/src/main/java/com/warxim/petep/gui/guide/internal/IntroductionGuide.java b/src/main/java/com/warxim/petep/gui/guide/internal/IntroductionGuide.java new file mode 100644 index 0000000..2805dd6 --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/guide/internal/IntroductionGuide.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.guide.internal; + +import com.warxim.petep.gui.guide.Guide; + +/** Introduction to PETEP. */ +public final class IntroductionGuide extends Guide { + @Override + public String getTitle() { + return "Introduction"; + } + + @Override + public String getHtml() { + return loadHtmlResource("/html/guide/internal/IntroductionGuide.html"); + } +} diff --git a/src/main/java/com/warxim/petep/gui/guide/internal/TipsAndTricksGuide.java b/src/main/java/com/warxim/petep/gui/guide/internal/TipsAndTricksGuide.java new file mode 100644 index 0000000..97dcf7d --- /dev/null +++ b/src/main/java/com/warxim/petep/gui/guide/internal/TipsAndTricksGuide.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.gui.guide.internal; + +import com.warxim.petep.gui.guide.Guide; + +/** Tips & tricks for using PETEP. */ +public final class TipsAndTricksGuide extends Guide { + @Override + public String getTitle() { + return "Tips & Tricks"; + } + + @Override + public String getHtml() { + return loadHtmlResource("/html/guide/internal/TipsAndTricksGuide.html"); + } +} diff --git a/src/main/java/com/warxim/petep/helper/DefaultExtensionHelper.java b/src/main/java/com/warxim/petep/helper/DefaultExtensionHelper.java new file mode 100644 index 0000000..0aef65c --- /dev/null +++ b/src/main/java/com/warxim/petep/helper/DefaultExtensionHelper.java @@ -0,0 +1,126 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.helper; + +import java.util.Collections; +import java.util.List; +import com.warxim.petep.Bundle; +import com.warxim.petep.common.ContextType; +import com.warxim.petep.core.listener.PetepListener; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.proxy.factory.ProxyModuleFactory; +import com.warxim.petep.proxy.module.ProxyModule; + +/** Default extension helper implementation. */ +public final class DefaultExtensionHelper implements ExtensionHelper { + private final Bundle bundle; + + /** Constructor of default extension helper. */ + public DefaultExtensionHelper(Bundle bundle) { + this.bundle = bundle; + } + + /* + * PROJECT INFO + */ + @Override + public String getProjectName() { + return bundle.getProject().getName(); + } + + @Override + public String getProjectDescription() { + return bundle.getProject().getDescription(); + } + + /* + * APPLICATION INFO + */ + @Override + public ContextType getContextType() { + return bundle.getContextType(); + } + + /* + * MODULES + */ + @Override + public boolean registerProxyModuleFactory(ProxyModuleFactory factory) { + return bundle.getProxyModuleFactoryManager().registerModuleFactory(factory); + } + + @Override + public boolean unregisterProxyModuleFactory(ProxyModuleFactory factory) { + return bundle.getProxyModuleFactoryManager().unregisterModuleFactory(factory); + } + + @Override + public boolean registerInterceptorModuleFactory(InterceptorModuleFactory factory) { + return bundle.getInterceptorModuleFactoryManager().registerModuleFactory(factory); + } + + @Override + public boolean unregisterInterceptorModuleFactory(InterceptorModuleFactory factory) { + return bundle.getInterceptorModuleFactoryManager().unregisterModuleFactory(factory); + } + + /* + * LISTENERS + */ + @Override + public void registerPetepListener(PetepListener listener) { + bundle.getPetepListenerManager().registerListener(listener); + } + + @Override + public void unregisterPetepListener(PetepListener listener) { + bundle.getPetepListenerManager().unregisterListener(listener); + } + + /* + * EXTENSIONS + */ + @Override + public List getExtensions() { + return bundle.getExtensionManager().getList(); + } + + /* + * Modules + */ + @Override + public List getInterceptorModulesC2S() { + return Collections.unmodifiableList(bundle.getInterceptorModuleContainerC2S().getList()); + } + + @Override + public List getInterceptorModulesS2C() { + return Collections.unmodifiableList(bundle.getInterceptorModuleContainerS2C().getList()); + } + + @Override + public List getProxyModules() { + return Collections.unmodifiableList(bundle.getProxyModuleContainer().getList()); + } + + @Override + public Extension getExtension(String code) { + return bundle.getExtensionManager().getExtension(code); + } +} diff --git a/src/main/java/com/warxim/petep/helper/DefaultGuiHelper.java b/src/main/java/com/warxim/petep/helper/DefaultGuiHelper.java new file mode 100644 index 0000000..5f42b16 --- /dev/null +++ b/src/main/java/com/warxim/petep/helper/DefaultGuiHelper.java @@ -0,0 +1,68 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.helper; + +import com.warxim.petep.gui.GuiBundle; +import com.warxim.petep.gui.guide.Guide; +import javafx.application.Platform; +import javafx.scene.Node; +import javafx.scene.image.Image; + +/** Default GUI helper implementation. */ +public final class DefaultGuiHelper implements GuiHelper { + private final GuiBundle bundle; + + /** Constructor of default GUI helper. */ + public DefaultGuiHelper(GuiBundle bundle) { + this.bundle = bundle; + } + + @Override + public void registerTab(String title, Node node) { + Platform.runLater(() -> bundle.getApplicationController().registerTab(title, node)); + } + + @Override + public void registerSettingsTab(String title, Node node) { + Platform.runLater(() -> bundle.getSettingsController().registerTab(title, node)); + } + + @Override + public void unregisterTab(Node node) { + Platform.runLater(() -> bundle.getApplicationController().unregisterTab(node)); + } + + @Override + public void unregisterSettingsTab(Node node) { + Platform.runLater(() -> bundle.getSettingsController().unregisterTab(node)); + } + + @Override + public void registerGuide(Guide guide) { + bundle.getGuideManager().add(guide); + } + + @Override + public void unregisterGuide(Guide guide) { + bundle.getGuideManager().remove(guide); + } + + @Override + public Image getPetepIcon() { + return GuiBundle.getInstance().getPetepIcon(); + } +} diff --git a/src/main/java/com/warxim/petep/helper/DefaultPetepHelper.java b/src/main/java/com/warxim/petep/helper/DefaultPetepHelper.java new file mode 100644 index 0000000..b26b470 --- /dev/null +++ b/src/main/java/com/warxim/petep/helper/DefaultPetepHelper.java @@ -0,0 +1,87 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.helper; + +import java.util.List; +import com.warxim.petep.core.PETEP; +import com.warxim.petep.core.PetepState; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.interceptor.worker.Interceptor; +import com.warxim.petep.proxy.worker.Proxy; + +/** Default implementation of PETEP helper. */ +public final class DefaultPetepHelper implements PetepHelper { + private final PETEP petep; + + /** Constructor of default PETEP helper implementation. */ + public DefaultPetepHelper(PETEP petep) { + this.petep = petep; + } + + @Override + public PetepState getState() { + return petep.getState(); + } + + @Override + public void processPdu(PDU pdu) { + if (pdu.getDestination() == PduDestination.SERVER) { + petep.processC2S(pdu); + } else { + petep.processS2C(pdu); + } + } + + @Override + public void processPdu(PDU pdu, int interceptorId) { + if (pdu.getDestination() == PduDestination.SERVER) { + petep.processC2S(pdu, interceptorId); + } else { + petep.processS2C(pdu, interceptorId); + } + } + + @Override + public void sendPdu(PDU pdu) { + if (pdu.getDestination() == PduDestination.SERVER) { + petep.sendC2S(pdu); + } else { + petep.sendS2C(pdu); + } + } + + @Override + public List getProxies() { + return petep.getProxyManager().getList(); + } + + @Override + public Proxy getProxy(String code) { + return petep.getProxyManager().get(code); + } + + @Override + public List getInterceptorsC2S() { + return petep.getInterceptorManagerC2S().getList(); + } + + @Override + public List getInterceptorsS2C() { + return petep.getInterceptorManagerS2C().getList(); + } +} diff --git a/src/main/java/com/warxim/petep/helper/ExtensionHelper.java b/src/main/java/com/warxim/petep/helper/ExtensionHelper.java new file mode 100644 index 0000000..8beb66d --- /dev/null +++ b/src/main/java/com/warxim/petep/helper/ExtensionHelper.java @@ -0,0 +1,86 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.helper; + +import java.util.List; +import com.warxim.petep.common.ContextType; +import com.warxim.petep.core.listener.PetepListener; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.proxy.factory.ProxyModuleFactory; +import com.warxim.petep.proxy.module.ProxyModule; + +/** + * Helper for extensions that allows extensions to use internal components, register module + * factories and get information about the project. + */ +@PetepAPI +public interface ExtensionHelper { + /* + * PROJECT INFO + */ + String getProjectName(); + + String getProjectDescription(); + + /* + * APPLICATION INFO + */ + /** Returns context type (GUI / COMMAND_LINE). */ + ContextType getContextType(); + + /* + * MODULES + */ + boolean registerProxyModuleFactory(ProxyModuleFactory factory); + + boolean unregisterProxyModuleFactory(ProxyModuleFactory factory); + + boolean registerInterceptorModuleFactory(InterceptorModuleFactory factory); + + boolean unregisterInterceptorModuleFactory(InterceptorModuleFactory factory); + + /* + * LISTENERS + */ + void registerPetepListener(PetepListener listener); + + void unregisterPetepListener(PetepListener listener); + + /* + * EXTENSIONS + */ + /** Returns list of extensions loaded in the project. */ + List getExtensions(); + + /** Returns extension of a given code or null if that extension is not loaded in the project. */ + Extension getExtension(String code); + + /* + * MODULES + */ + /** Returns list of interceptor modules in direction C2S (Client -> Server). */ + List getInterceptorModulesC2S(); + + /** Returns list of interceptor modules in direction S2C (Client <- Server). */ + List getInterceptorModulesS2C(); + + /** Returns list of proxy modules. */ + List getProxyModules(); +} diff --git a/src/main/java/com/warxim/petep/helper/GuiHelper.java b/src/main/java/com/warxim/petep/helper/GuiHelper.java new file mode 100644 index 0000000..2424d3d --- /dev/null +++ b/src/main/java/com/warxim/petep/helper/GuiHelper.java @@ -0,0 +1,55 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.helper; + +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.gui.guide.Guide; +import javafx.scene.Node; +import javafx.scene.image.Image; + +/** + * Helper for extensions with GUI that allows extensions to use internal GUI components, register + * GUI components etc. + */ +@PetepAPI +public interface GuiHelper { + /* + * APPLICATION TABS + */ + void registerTab(String title, Node node); + + void unregisterTab(Node node); + + /* + * SETTINGS + */ + void registerSettingsTab(String title, Node node); + + void unregisterSettingsTab(Node node); + + /* + * GUIDES + */ + void registerGuide(Guide guide); + + void unregisterGuide(Guide guide); + + /* + * OTHER + */ + Image getPetepIcon(); +} diff --git a/src/main/java/com/warxim/petep/helper/PetepHelper.java b/src/main/java/com/warxim/petep/helper/PetepHelper.java new file mode 100644 index 0000000..d2d62bc --- /dev/null +++ b/src/main/java/com/warxim/petep/helper/PetepHelper.java @@ -0,0 +1,64 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.helper; + +import java.util.List; +import com.warxim.petep.core.PetepState; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.interceptor.worker.Interceptor; +import com.warxim.petep.proxy.worker.Proxy; + +/** PETEP helper. */ +@PetepAPI +public interface PetepHelper { + /* + * GENERAL + */ + /** Returns PETEP state. */ + PetepState getState(); + + /* + * PDUS + */ + /** Processes PDU in PETEP. */ + void processPdu(PDU pdu); + + /** Processes PDU in PETEP starting in specified interceptor. */ + void processPdu(PDU pdu, int interceptorId); + + /** Sends PDU outside of the PETEP (to the Internet, ...). */ + void sendPdu(PDU pdu); + + /* + * PROXIES + */ + /** Returns list of proxies. */ + List getProxies(); + + /** Returns proxy by given code. */ + Proxy getProxy(String code); + + /* + * INTERCEPTORS + */ + /** Returns list of interceptors in direction C2S. (Client -> Server) */ + List getInterceptorsC2S(); + + /** Returns list of interceptors in direction S2C. (Client <- Server) */ + List getInterceptorsS2C(); +} diff --git a/src/main/java/com/warxim/petep/interceptor/factory/InterceptorModuleFactory.java b/src/main/java/com/warxim/petep/interceptor/factory/InterceptorModuleFactory.java new file mode 100644 index 0000000..afaf879 --- /dev/null +++ b/src/main/java/com/warxim/petep/interceptor/factory/InterceptorModuleFactory.java @@ -0,0 +1,30 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.interceptor.factory; + +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.module.ModuleFactory; + +/** Interceptor module interface. */ +@PetepAPI +public abstract class InterceptorModuleFactory extends ModuleFactory { + public InterceptorModuleFactory(Extension extension) { + super(extension); + } +} diff --git a/src/main/java/com/warxim/petep/interceptor/factory/InterceptorModuleFactoryManager.java b/src/main/java/com/warxim/petep/interceptor/factory/InterceptorModuleFactoryManager.java new file mode 100644 index 0000000..06fd66b --- /dev/null +++ b/src/main/java/com/warxim/petep/interceptor/factory/InterceptorModuleFactoryManager.java @@ -0,0 +1,24 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.interceptor.factory; + +import com.warxim.petep.module.ModuleFactoryManager; + +/** Interceptor module factory manager. */ +public class InterceptorModuleFactoryManager + extends ModuleFactoryManager { +} diff --git a/src/main/java/com/warxim/petep/interceptor/module/InterceptorModule.java b/src/main/java/com/warxim/petep/interceptor/module/InterceptorModule.java new file mode 100644 index 0000000..98307b7 --- /dev/null +++ b/src/main/java/com/warxim/petep/interceptor/module/InterceptorModule.java @@ -0,0 +1,39 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.interceptor.module; + +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.factory.InterceptorModuleFactory; +import com.warxim.petep.interceptor.worker.Interceptor; +import com.warxim.petep.module.Module; + +/** Interceptor module provides interceptor workers when PETEP starts. */ +@PetepAPI +public abstract class InterceptorModule extends Module { + public InterceptorModule( + InterceptorModuleFactory factory, + String code, + String name, + String description, + boolean enabled) { + super(factory, code, name, description, enabled); + } + + /** Creates interceptor with specified ID. */ + public abstract Interceptor createInterceptor(int id, PetepHelper helper); +} diff --git a/src/main/java/com/warxim/petep/interceptor/module/InterceptorModuleContainer.java b/src/main/java/com/warxim/petep/interceptor/module/InterceptorModuleContainer.java new file mode 100644 index 0000000..14c73eb --- /dev/null +++ b/src/main/java/com/warxim/petep/interceptor/module/InterceptorModuleContainer.java @@ -0,0 +1,27 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.interceptor.module; + +import java.util.List; +import com.warxim.petep.module.ModuleContainer; + +/** Container that contains interceptor modules. */ +public class InterceptorModuleContainer extends ModuleContainer { + public InterceptorModuleContainer(List modules) { + super(modules); + } +} diff --git a/src/main/java/com/warxim/petep/interceptor/worker/Interceptor.java b/src/main/java/com/warxim/petep/interceptor/worker/Interceptor.java new file mode 100644 index 0000000..cc9d644 --- /dev/null +++ b/src/main/java/com/warxim/petep/interceptor/worker/Interceptor.java @@ -0,0 +1,49 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.interceptor.worker; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.module.ModuleWorker; + +/** Interceptor base class. */ +@PetepAPI +public abstract class Interceptor extends ModuleWorker { + /** ID of interceptor (interceptor index in interceptors list). */ + protected final int id; + + public Interceptor(int id, InterceptorModule module, PetepHelper helper) { + super(module, helper); + this.id = id; + } + + /** Prepares instance for intercepting. */ + public abstract boolean prepare(); + + /** Intercepts PDUs. */ + public abstract boolean intercept(PDU pdu); + + /** Stops intercepting. */ + public abstract void stop(); + + /** Returns interceptor ID. */ + public final int getId() { + return id; + } +} diff --git a/src/main/java/com/warxim/petep/interceptor/worker/InterceptorExecutor.java b/src/main/java/com/warxim/petep/interceptor/worker/InterceptorExecutor.java new file mode 100644 index 0000000..c9408ad --- /dev/null +++ b/src/main/java/com/warxim/petep/interceptor/worker/InterceptorExecutor.java @@ -0,0 +1,108 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.interceptor.worker; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.function.Consumer; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduQueue; + +/** Interceptor executor executes interceptors and creates queues. */ +public final class InterceptorExecutor { + private final InterceptorManager manager; + private final List queues; + private final List workers; + private final ExecutorService executor; + private final Consumer consumer; + + public InterceptorExecutor(InterceptorManager manager, Consumer consumer) { + this.manager = manager; + this.consumer = consumer; + + workers = new ArrayList<>(manager.size()); + queues = new ArrayList<>(manager.size() + 1); + + queues.add(new PduQueue()); + + // Create queues and workers with assigned queues. + for (Interceptor interceptor : manager.getList()) { + int index = queues.size(); + + // Create new queue. + queues.add(new PduQueue()); + + // Create new worker with input and output queues. + workers.add(new InterceptorWorker(interceptor, queues.get(index - 1), queues.get(index))); + } + + // Create fixed thread pool for workers and consumer. + executor = Executors.newFixedThreadPool(queues.size()); + } + + /** Runs prepare method on all interceptors. */ + public boolean prepare() { + return manager.getList().parallelStream().allMatch(Interceptor::prepare); + } + + /** Starts interceptors. */ + public void start() { + // Start all workers. + for (InterceptorWorker worker : workers) { + executor.submit(worker); + } + + // Start consumer work. + executor.submit(this::work); + } + + /** Processes PDUs in consumer. */ + private void work() { + PduQueue queue = queues.get(queues.size() - 1); + + PDU pdu; + try { + while ((pdu = queue.take()) != null) { + consumer.accept(pdu); + } + } catch (InterruptedException e) { + // Closing... + Thread.currentThread().interrupt(); + } + } + + /** Stops interceptors. */ + public void stop() { + // Stop workers. + executor.shutdownNow(); + + // Call stop on interceptors. + manager.getList().parallelStream().forEach(Interceptor::stop); + } + + /** Puts PDU into first queue. */ + public void intercept(PDU pdu) { + queues.get(0).add(pdu); + } + + /** Puts PDU into specified queue (for specified interceptor). */ + public void intercept(PDU pdu, int interceptorId) { + queues.get(interceptorId).add(pdu); + } +} diff --git a/src/main/java/com/warxim/petep/interceptor/worker/InterceptorManager.java b/src/main/java/com/warxim/petep/interceptor/worker/InterceptorManager.java new file mode 100644 index 0000000..64bc9ba --- /dev/null +++ b/src/main/java/com/warxim/petep/interceptor/worker/InterceptorManager.java @@ -0,0 +1,52 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.interceptor.worker; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.interceptor.module.InterceptorModule; +import com.warxim.petep.interceptor.module.InterceptorModuleContainer; +import com.warxim.petep.module.ModuleWorkerManager; + +/** Interceptor manager. */ +public final class InterceptorManager extends ModuleWorkerManager { + public InterceptorManager(PetepHelper helper, InterceptorModuleContainer container) { + Map tempMap = new HashMap<>((int) (container.size() / 0.75) + 1, 0.75f); + List tempList = new ArrayList<>(container.size()); + + // Create interceptors using modules. + for (InterceptorModule module : container.getList()) { + // Skip disabled interceptor. + if (!module.isEnabled()) { + continue; + } + + // Create interceptor. + Interceptor interceptor = module.createInterceptor(tempList.size(), helper); + tempList.add(interceptor); + tempMap.put(module.getCode(), interceptor); + } + + // Create unmodifiable collections. + map = Collections.unmodifiableMap(tempMap); + list = Collections.unmodifiableList(tempList); + } +} diff --git a/src/main/java/com/warxim/petep/interceptor/worker/InterceptorWorker.java b/src/main/java/com/warxim/petep/interceptor/worker/InterceptorWorker.java new file mode 100644 index 0000000..96edf3a --- /dev/null +++ b/src/main/java/com/warxim/petep/interceptor/worker/InterceptorWorker.java @@ -0,0 +1,60 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.interceptor.worker; + +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduQueue; + +/** + * Interceptor worker operates with PDUs through input and output queue by calling subordinate + * interceptor. + */ +public final class InterceptorWorker implements Runnable { + private final Interceptor interceptor; + + private final PduQueue in; + private final PduQueue out; + + public InterceptorWorker(Interceptor interceptor, PduQueue in, PduQueue out) { + this.interceptor = interceptor; + this.in = in; + this.out = out; + } + + /** Runs worker. */ + @Override + public void run() { + try { + PDU pdu; + + // Wait for PDU to appear in the input queue. + while ((pdu = in.take()) != null) { + // Send the PDU to interceptor and if it returns true, put it into output queue. + if (interceptor.intercept(pdu)) { + // Sets last interceptor to current interceptor. + pdu.setLastInterceptor(interceptor); + + // Puts the PDU to outgoing queue. + out.add(pdu); + } + } + } catch (InterruptedException e) { + // Shutdown. + Thread.currentThread().interrupt(); + } + } +} diff --git a/src/main/java/com/warxim/petep/module/Module.java b/src/main/java/com/warxim/petep/module/Module.java new file mode 100644 index 0000000..83ef79e --- /dev/null +++ b/src/main/java/com/warxim/petep/module/Module.java @@ -0,0 +1,66 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.module; + +import com.warxim.petep.extension.PetepAPI; + +/** Module base class. */ +@PetepAPI +public abstract class Module> { + protected final String code; + protected final String name; + protected final String description; + protected final boolean enabled; + protected final F factory; + + /** Module constructor. */ + public Module(F factory, String code, String name, String description, boolean enabled) { + this.code = code; + this.name = name; + this.description = description; + this.enabled = enabled; + this.factory = factory; + } + + /* + * GETTERS + */ + public final boolean isEnabled() { + return enabled; + } + + public final String getCode() { + return code; + } + + public final String getName() { + return name; + } + + public final String getDescription() { + return description; + } + + public final F getFactory() { + return factory; + } + + @Override + public String toString() { + return name + " (" + code + ")"; + } +} diff --git a/src/main/java/com/warxim/petep/module/ModuleContainer.java b/src/main/java/com/warxim/petep/module/ModuleContainer.java new file mode 100644 index 0000000..a0e71e7 --- /dev/null +++ b/src/main/java/com/warxim/petep/module/ModuleContainer.java @@ -0,0 +1,81 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.module; + +import java.util.Collections; +import java.util.List; + +/** Module container base class. */ +public abstract class ModuleContainer> { + /** List of modules. */ + protected List modules; + + /** Creates module container using specified module list. */ + public ModuleContainer(List modules) { + this.modules = modules; + } + + /** Adds module to manager. */ + public void add(M module) { + modules.add(module); + } + + /** Returns module by code. */ + public M get(String code) { + for (M module : modules) { + if (module.getCode().equals(code)) { + return module; + } + } + return null; + } + + /** Returns true if manager contains module with specified code. */ + public boolean contains(String code) { + for (M module : modules) { + if (module.getCode().equals(code)) { + return true; + } + } + return false; + } + + /** Replaces module with a new one. */ + public void replace(M oldModule, M newModule) { + modules.set(modules.indexOf(oldModule), newModule); + } + + /** Removes module with given code. */ + public void remove(M module) { + modules.remove(module); + } + + /** Swaps modules. */ + public void swap(int what, int with) { + Collections.swap(modules, what, with); + } + + /** Returns number of modules. */ + public int size() { + return modules.size(); + } + + /** Returns list of modules. */ + public List getList() { + return modules; + } +} diff --git a/src/main/java/com/warxim/petep/module/ModuleFactory.java b/src/main/java/com/warxim/petep/module/ModuleFactory.java new file mode 100644 index 0000000..8424d69 --- /dev/null +++ b/src/main/java/com/warxim/petep/module/ModuleFactory.java @@ -0,0 +1,43 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.module; + +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.PetepAPI; + +/** Module factory base class. */ +@PetepAPI +public abstract class ModuleFactory> { + protected final Extension extension; + + public ModuleFactory(Extension extension) { + this.extension = extension; + } + + public final Extension getExtension() { + return extension; + } + + /** Returns name of the factory. */ + public abstract String getName(); + + /** Returns unique code of the factory. */ + public abstract String getCode(); + + /** Creates module with specified parameters. */ + public abstract M createModule(String code, String name, String description, boolean enabled); +} diff --git a/src/main/java/com/warxim/petep/module/ModuleFactoryManager.java b/src/main/java/com/warxim/petep/module/ModuleFactoryManager.java new file mode 100644 index 0000000..8d4f2dc --- /dev/null +++ b/src/main/java/com/warxim/petep/module/ModuleFactoryManager.java @@ -0,0 +1,67 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.module; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +/** Module manager base class. */ +public abstract class ModuleFactoryManager> { + /** Map of factories (key = code, value = factory). */ + private final Map factoryMap; + + /** List of factories. */ + private final List factoryList; + + /** Module manager constructor. */ + public ModuleFactoryManager() { + factoryMap = new ConcurrentHashMap<>(); + factoryList = new CopyOnWriteArrayList<>(); + } + + /** Registers module. */ + public boolean registerModuleFactory(F factory) { + if (factoryMap.putIfAbsent(factory.getCode(), factory) == null) { + factoryList.add(factory); + return true; + } + return false; + } + + /** Unregisters module. */ + public boolean unregisterModuleFactory(F module) { + factoryMap.remove(module.getCode()); + return factoryList.remove(module); + } + + /** Returns map of module factories (key = code, value = factory). */ + public Map getMap() { + return factoryMap; + } + + /** Returns list of module factories. */ + public List getList() { + return factoryList; + } + + /** Returns factory by code. */ + public F getModuleFactory(String code) { + return factoryMap.get(code); + } +} diff --git a/src/main/java/com/warxim/petep/module/ModuleWorker.java b/src/main/java/com/warxim/petep/module/ModuleWorker.java new file mode 100644 index 0000000..eff651e --- /dev/null +++ b/src/main/java/com/warxim/petep/module/ModuleWorker.java @@ -0,0 +1,50 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.module; + +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.helper.PetepHelper; + +/** Instance base class. */ +@PetepAPI +public abstract class ModuleWorker> { + /** PETEP helper for current running PETEP core instance. */ + protected final PetepHelper helper; + + /** Parent module. */ + protected final M module; + + public ModuleWorker(M module, PetepHelper helper) { + this.helper = helper; + this.module = module; + } + + /** Returns parent module. */ + public final M getModule() { + return module; + } + + /** Returns PetepHelper of current PETEP core instance. */ + public final PetepHelper getHelper() { + return helper; + } + + @Override + public String toString() { + return module.toString(); + } +} diff --git a/src/main/java/com/warxim/petep/module/ModuleWorkerManager.java b/src/main/java/com/warxim/petep/module/ModuleWorkerManager.java new file mode 100644 index 0000000..1213f9c --- /dev/null +++ b/src/main/java/com/warxim/petep/module/ModuleWorkerManager.java @@ -0,0 +1,49 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.module; + +import java.util.List; +import java.util.Map; + +/** Module worker manager. */ +public abstract class ModuleWorkerManager> { + /** Map of module workers. */ + protected Map map; + + /** List of module workers. */ + protected List list; + + /** Returns module worker by code. */ + public W get(String code) { + return map.get(code); + } + + /** Returns module worker list. */ + public List getList() { + return list; + } + + /** Returns module worker map. */ + public Map getMap() { + return map; + } + + /** Returns number of module workers. */ + public int size() { + return list.size(); + } +} diff --git a/src/main/java/com/warxim/petep/persistence/Configurable.java b/src/main/java/com/warxim/petep/persistence/Configurable.java new file mode 100644 index 0000000..51337b0 --- /dev/null +++ b/src/main/java/com/warxim/petep/persistence/Configurable.java @@ -0,0 +1,29 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.persistence; + +import com.warxim.petep.extension.PetepAPI; + +/** Configurable interface that allows modules and extensions to be configured. */ +@PetepAPI +public interface Configurable { + /** Returns configuration to be saved. */ + C saveConfig(); + + /** Loads configuration. */ + void loadConfig(C config); +} diff --git a/src/main/java/com/warxim/petep/persistence/Configurator.java b/src/main/java/com/warxim/petep/persistence/Configurator.java new file mode 100644 index 0000000..9cef947 --- /dev/null +++ b/src/main/java/com/warxim/petep/persistence/Configurator.java @@ -0,0 +1,28 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.persistence; + +import java.io.IOException; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.gui.component.ConfigPane; + +/** Configurator interface that creates graphical configuration pane for module configuration. */ +@PetepAPI +@FunctionalInterface +public interface Configurator { + ConfigPane createConfigPane() throws IOException; +} diff --git a/src/main/java/com/warxim/petep/persistence/Storable.java b/src/main/java/com/warxim/petep/persistence/Storable.java new file mode 100644 index 0000000..913ecf6 --- /dev/null +++ b/src/main/java/com/warxim/petep/persistence/Storable.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.persistence; + +import com.warxim.petep.extension.PetepAPI; + +/** + * Allows extensions and modules to define their own data stores that are serialized to JSON + * structure and saved to project files. + */ +@PetepAPI +public interface Storable { + /** Returns store to be saved. */ + S saveStore(); + + /** Loads store. */ + void loadStore(S store); +} diff --git a/src/main/java/com/warxim/petep/project/Project.java b/src/main/java/com/warxim/petep/project/Project.java new file mode 100644 index 0000000..e81297b --- /dev/null +++ b/src/main/java/com/warxim/petep/project/Project.java @@ -0,0 +1,36 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.project; + +/** PETEP project. */ +public final class Project { + private final String name; + private final String description; + + public Project(String name, String description) { + this.name = name; + this.description = description; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } +} diff --git a/src/main/java/com/warxim/petep/proxy/factory/ProxyFactoryModuleManager.java b/src/main/java/com/warxim/petep/proxy/factory/ProxyFactoryModuleManager.java new file mode 100644 index 0000000..422360b --- /dev/null +++ b/src/main/java/com/warxim/petep/proxy/factory/ProxyFactoryModuleManager.java @@ -0,0 +1,23 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.proxy.factory; + +import com.warxim.petep.module.ModuleFactoryManager; + +/** Proxy module factory manager. */ +public final class ProxyFactoryModuleManager extends ModuleFactoryManager { +} diff --git a/src/main/java/com/warxim/petep/proxy/factory/ProxyModuleFactory.java b/src/main/java/com/warxim/petep/proxy/factory/ProxyModuleFactory.java new file mode 100644 index 0000000..f5f188c --- /dev/null +++ b/src/main/java/com/warxim/petep/proxy/factory/ProxyModuleFactory.java @@ -0,0 +1,43 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.proxy.factory; + +import java.io.IOException; +import com.warxim.petep.extension.Extension; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.gui.component.PduMetadataPane; +import com.warxim.petep.module.ModuleFactory; +import com.warxim.petep.proxy.module.ProxyModule; +import com.warxim.petep.proxy.serizalization.ProxyDeserializer; +import com.warxim.petep.proxy.serizalization.ProxySerializer; + +/** Proxy module factory. */ +@PetepAPI +public abstract class ProxyModuleFactory extends ModuleFactory { + public ProxyModuleFactory(Extension extension) { + super(extension); + } + + /** Creates PDU metadata component for modules of this factory. */ + public abstract PduMetadataPane createPduMetadataPane() throws IOException; + + /** Returns proxy serializer. */ + public abstract ProxySerializer getSerializer(); + + /** Returns proxy deserializer. */ + public abstract ProxyDeserializer getDeserializer(); +} diff --git a/src/main/java/com/warxim/petep/proxy/module/ProxyModule.java b/src/main/java/com/warxim/petep/proxy/module/ProxyModule.java new file mode 100644 index 0000000..b6629b1 --- /dev/null +++ b/src/main/java/com/warxim/petep/proxy/module/ProxyModule.java @@ -0,0 +1,39 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.proxy.module; + +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.module.Module; +import com.warxim.petep.proxy.factory.ProxyModuleFactory; +import com.warxim.petep.proxy.worker.Proxy; + +/** Proxy module. */ +@PetepAPI +public abstract class ProxyModule extends Module { + public ProxyModule( + ProxyModuleFactory factory, + String code, + String name, + String description, + boolean enabled) { + super(factory, code, name, description, enabled); + } + + /** Creates proxy worker. */ + public abstract Proxy createProxy(PetepHelper helper); +} diff --git a/src/main/java/com/warxim/petep/proxy/module/ProxyModuleContainer.java b/src/main/java/com/warxim/petep/proxy/module/ProxyModuleContainer.java new file mode 100644 index 0000000..9b36c10 --- /dev/null +++ b/src/main/java/com/warxim/petep/proxy/module/ProxyModuleContainer.java @@ -0,0 +1,27 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.proxy.module; + +import java.util.List; +import com.warxim.petep.module.ModuleContainer; + +/** Proxy module container. */ +public final class ProxyModuleContainer extends ModuleContainer { + public ProxyModuleContainer(List modules) { + super(modules); + } +} diff --git a/src/main/java/com/warxim/petep/proxy/serizalization/ProxyDeserializer.java b/src/main/java/com/warxim/petep/proxy/serizalization/ProxyDeserializer.java new file mode 100644 index 0000000..b5033bb --- /dev/null +++ b/src/main/java/com/warxim/petep/proxy/serizalization/ProxyDeserializer.java @@ -0,0 +1,40 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.proxy.serizalization; + +import java.util.Map; +import java.util.Set; +import com.warxim.petep.core.connection.Connection; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.core.pdu.PduDestination; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.proxy.worker.Proxy; + +/** Proxy deserializer. */ +@PetepAPI +@FunctionalInterface +public interface ProxyDeserializer { + /** Deserializes PDU from its parts and serialized meta data. */ + PDU deserializePdu( + Proxy proxy, + Connection connection, + PduDestination destination, + byte[] buffer, + int size, + Set tags, + Map serializedMetadata); +} diff --git a/src/main/java/com/warxim/petep/proxy/serizalization/ProxySerializer.java b/src/main/java/com/warxim/petep/proxy/serizalization/ProxySerializer.java new file mode 100644 index 0000000..20bfcbc --- /dev/null +++ b/src/main/java/com/warxim/petep/proxy/serizalization/ProxySerializer.java @@ -0,0 +1,29 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.proxy.serizalization; + +import java.util.Map; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.PetepAPI; + +/** Proxy serializer. */ +@PetepAPI +@FunctionalInterface +public interface ProxySerializer { + /** Serializes PDU meta data to string. */ + Map serializePduMetadata(PDU pdu); +} diff --git a/src/main/java/com/warxim/petep/proxy/worker/Proxy.java b/src/main/java/com/warxim/petep/proxy/worker/Proxy.java new file mode 100644 index 0000000..47beb38 --- /dev/null +++ b/src/main/java/com/warxim/petep/proxy/worker/Proxy.java @@ -0,0 +1,43 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.proxy.worker; + +import com.warxim.petep.core.connection.ConnectionManager; +import com.warxim.petep.extension.PetepAPI; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.module.ModuleWorker; +import com.warxim.petep.proxy.module.ProxyModule; + +/** Proxy base class. */ +@PetepAPI +public abstract class Proxy extends ModuleWorker { + public Proxy(ProxyModule module, PetepHelper helper) { + super(module, helper); + } + + /** Prepares proxy to start. */ + public abstract boolean prepare(); + + /** Starts proxy. */ + public abstract boolean start(); + + /** Stops proxy. */ + public abstract void stop(); + + /** Returns proxy connection manager. */ + public abstract ConnectionManager getConnectionManager(); +} diff --git a/src/main/java/com/warxim/petep/proxy/worker/ProxyExecutor.java b/src/main/java/com/warxim/petep/proxy/worker/ProxyExecutor.java new file mode 100644 index 0000000..f325f25 --- /dev/null +++ b/src/main/java/com/warxim/petep/proxy/worker/ProxyExecutor.java @@ -0,0 +1,41 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.proxy.worker; + +/** Proxy executor executes proxy workers. */ +public final class ProxyExecutor { + private final ProxyManager manager; + + public ProxyExecutor(ProxyManager manager) { + this.manager = manager; + } + + /** Runs prepare method in all proxy workers. */ + public boolean prepare() { + return manager.getList().parallelStream().allMatch(Proxy::prepare); + } + + /** Runs start method in all proxy workers. */ + public boolean start() { + return manager.getList().parallelStream().allMatch(Proxy::start); + } + + /** Runs stop method in all proxy workers. */ + public void stop() { + manager.getList().parallelStream().forEach(Proxy::stop); + } +} diff --git a/src/main/java/com/warxim/petep/proxy/worker/ProxyManager.java b/src/main/java/com/warxim/petep/proxy/worker/ProxyManager.java new file mode 100644 index 0000000..afea871 --- /dev/null +++ b/src/main/java/com/warxim/petep/proxy/worker/ProxyManager.java @@ -0,0 +1,51 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.proxy.worker; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.warxim.petep.helper.PetepHelper; +import com.warxim.petep.module.ModuleWorkerManager; +import com.warxim.petep.proxy.module.ProxyModule; +import com.warxim.petep.proxy.module.ProxyModuleContainer; + +/** Proxy manager. */ +public final class ProxyManager extends ModuleWorkerManager { + public ProxyManager(PetepHelper helper, ProxyModuleContainer container) { + Map tempMap = new HashMap<>((int) (container.size() / 0.75) + 1, 0.75f); + List tempList = new ArrayList<>(container.size()); + + // Create proxies using modules. + for (ProxyModule module : container.getList()) { + if (!module.isEnabled()) { + continue; + } + + // Create proxy and add it to collections. + Proxy proxy = module.createProxy(helper); + tempList.add(proxy); + tempMap.put(module.getCode(), proxy); + } + + // Create unmodifiable collections. + map = Collections.unmodifiableMap(tempMap); + list = Collections.unmodifiableList(tempList); + } +} diff --git a/src/main/java/com/warxim/petep/util/BytesUtils.java b/src/main/java/com/warxim/petep/util/BytesUtils.java new file mode 100644 index 0000000..4863803 --- /dev/null +++ b/src/main/java/com/warxim/petep/util/BytesUtils.java @@ -0,0 +1,202 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.util; + +import com.warxim.petep.extension.PetepAPI; + +/** Bytes utils. */ +@PetepAPI +public final class BytesUtils { + /** HEX symbols. */ + private static final char[] hexArray = "0123456789ABCDEF".toCharArray(); + + private BytesUtils() {} + + /** Converts bytes to string. */ + public static String bytesToString(byte[] buffer, int size) { + if (size == 0) { + return ""; + } + + char[] c = new char[size * 3]; + for (int j = 0; j < size; ++j) { + int v = buffer[j] & 0xFF; + c[j * 3] = hexArray[v >>> 4]; + c[j * 3 + 1] = hexArray[v & 0x0F]; + c[j * 3 + 2] = ' '; + } + return new String(c, 0, c.length - 1); + } + + /** Converts bytes to string. */ + public static String bytesToString(byte[] buffer) { + return bytesToString(buffer, buffer.length); + } + + /** Converts string to bytes. */ + public static byte[] stringToBytes(String s) { + int len = s.length(); + + byte[] buffer = new byte[(len + 1) / 3]; + for (int i = 0; i < len; i += 3) { + buffer[i / 3] = + (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)); + } + return buffer; + } + + /** + * Finds first occurrence of array inside of specified buffer, starting at specified offset. + * + * @return Returns index of the first occurrence or -1 if not found. + */ + public static int find(byte[] buffer, int size, int offset, byte[] array) { + for (int i = offset; i < size; ++i) { + if (buffer[i] != array[0]) { + continue; + } + + if (size - i < array.length) { + break; + } + + boolean found = true; + for (int j = 1; j < array.length; ++j) { + if (buffer[i + j] != array[j]) { + found = false; + break; + } + } + + if (found) { + return i; + } + } + + return -1; + } + + /** + * Finds specified occurrence of array inside of specified buffer, starting at specified offset. + * + * @return Returns index of the specified occurrence or -1 if not found. + */ + public static int findNth(byte[] buffer, int size, int offset, byte[] array, int n) { + int occurrence = 0; + + for (int i = offset; i < size; ++i) { + if (buffer[i] != array[0]) { + continue; + } + + if (size - i < array.length) { + break; + } + + boolean found = true; + for (int j = 1; j < array.length; ++j) { + if (buffer[i + j] != array[j]) { + found = false; + break; + } + } + + if (found) { + if (occurrence == n) { + return i; + } else { + ++occurrence; + } + } + } + + return -1; + } + + /** Returns true if the buffer contains specified "what" bytes. */ + public static boolean contains(byte[] buffer, int size, byte[] what) { + for (int i = 0; i < size; ++i) { + if (buffer[i] != what[0]) { + continue; + } + + if (size - i < what.length) { + break; + } + + boolean found = true; + for (int j = 1; j < what.length; ++j) { + if (buffer[i + j] != what[j]) { + found = false; + break; + } + } + + if (found) { + return true; + } + } + + return false; + } + + /** Returns true if the buffer contains specified "what" bytes at specified position. */ + public static boolean containsAt(byte[] buffer, int size, byte[] what, int position) { + if (size < position + what.length) { + return false; + } + + for (int i = 0; i < what.length; ++i) { + if (buffer[position + i] != what[i]) { + return false; + } + } + + return true; + } + + /** Returns true if the buffer ends with "what" bytes. */ + public static boolean endsWith(byte[] buffer, int size, byte[] what) { + if (size < what.length) { + return false; + } + + int first = size - what.length; + for (int i = 0; i < what.length; ++i) { + if (buffer[first + i] != what[i]) { + return false; + } + } + + return true; + } + + /** Returns true if the buffer starts with "what" bytes. */ + public static boolean startsWith(byte[] buffer, int size, byte[] what) { + if (size < what.length) { + return false; + } + + for (int i = 0; i < what.length; ++i) { + if (buffer[i] != what[i]) { + return false; + } + } + + return true; + } +} diff --git a/src/main/java/com/warxim/petep/util/ExtensionUtils.java b/src/main/java/com/warxim/petep/util/ExtensionUtils.java new file mode 100644 index 0000000..59bd11c --- /dev/null +++ b/src/main/java/com/warxim/petep/util/ExtensionUtils.java @@ -0,0 +1,94 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.util; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import com.warxim.petep.persistence.Configurable; +import com.warxim.petep.persistence.Configurator; +import com.warxim.petep.persistence.Storable; + +/** Extension utils. */ +public final class ExtensionUtils { + private ExtensionUtils() {} + + /** + * Determines store type using reflections. + * + * @returns Type or null if extension does not contain store. + */ + public static Type getStoreType(Object object) { + if (!(object instanceof Storable)) { + return null; + } + + Type[] genericInterfaces = object.getClass().getGenericInterfaces(); + + for (Type genericInterface : genericInterfaces) { + if (genericInterface instanceof ParameterizedType + && ((ParameterizedType) genericInterface).getRawType() == Storable.class) { + return ((ParameterizedType) genericInterface).getActualTypeArguments()[0]; + } + } + + return null; + } + + /** + * Determines configuration type using reflections. + * + * @returns Type or null if extension does not contain configuration. + */ + public static Type getConfigType(Object object) { + if (!(object instanceof Configurable)) { + return null; + } + + Type[] genericInterfaces = object.getClass().getGenericInterfaces(); + + for (Type genericInterface : genericInterfaces) { + if (genericInterface instanceof ParameterizedType + && ((ParameterizedType) genericInterface).getRawType() == Configurable.class) { + return ((ParameterizedType) genericInterface).getActualTypeArguments()[0]; + } + } + + return null; + } + + /** + * Determines configuration type using reflections. + * + * @returns Type or null if extension does not contain configuration. + */ + public static Type getConfiguratorType(Object object) { + if (!(object instanceof Configurator)) { + return null; + } + + Type[] genericInterfaces = object.getClass().getGenericInterfaces(); + + for (Type genericInterface : genericInterfaces) { + if (genericInterface instanceof ParameterizedType + && ((ParameterizedType) genericInterface).getRawType() == Configurator.class) { + return ((ParameterizedType) genericInterface).getActualTypeArguments()[0]; + } + } + + return null; + } +} diff --git a/src/main/java/com/warxim/petep/util/FileUtils.java b/src/main/java/com/warxim/petep/util/FileUtils.java new file mode 100644 index 0000000..7941612 --- /dev/null +++ b/src/main/java/com/warxim/petep/util/FileUtils.java @@ -0,0 +1,156 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.util; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.logging.Logger; +import java.util.stream.Stream; +import com.warxim.petep.Main; +import com.warxim.petep.extension.PetepAPI; + +/** File utils. */ +@PetepAPI +public final class FileUtils { + private static final String APP_DIR = initApplicationDirectory(); + + private FileUtils() {} + + /** Returns application directory. */ + public static String getApplicationDirectory() { + return APP_DIR; + } + + /** Returns application file. */ + public static File getApplicationFile(String path) { + if (Paths.get(path).isAbsolute()) { + // Absolute path + return new File(path); + } else { + // Relative path + return new File(FileUtils.getApplicationDirectory(), path); + } + } + + /** Returns application file absolute path. */ + public static String getApplicationFileAbsolutePath(String path) { + if (Paths.get(path).isAbsolute()) { + // Absolute path + return path; + } else { + // Relative path + return new File(FileUtils.getApplicationDirectory(), path).getAbsolutePath(); + } + } + + public static String applicationRelativize(Path path) { + return Paths.get(APP_DIR).relativize(path).toString(); + } + + public static String applicationRelativize(String path) { + return applicationRelativize(Paths.get(path)); + } + + public static String projectRelativize(Path path) { + return Paths.get(getProjectDirectory()).relativize(path).toString(); + } + + public static String projectRelativize(String path) { + return projectRelativize(Paths.get(path)); + } + + /** Returns project path. */ + public static File getProjectFile(String path) { + if (Paths.get(path).isAbsolute()) { + // Absolute path + return new File(path); + } else { + // Relative path + return new File(FileUtils.getProjectDirectory(), path); + } + } + + /** Returns absolute path of project file. */ + public static String getProjectFileAbsolutePath(String path) { + if (Paths.get(path).isAbsolute()) { + // Absolute path + return path; + } else { + // Relative path + return new File(FileUtils.getProjectDirectory(), path).getAbsolutePath(); + } + } + + /** Returns project directory. */ + public static String getProjectDirectory() { + return System.getProperty("user.dir"); + } + + /** Sets working directory (used internally). */ + public static void setProjectDirectory(String directory) { + System.setProperty("user.dir", directory); + } + + /** Returns true if the specified directory is empty. */ + public static boolean isDirectoryEmpty(File directory) { + return directory.list().length == 0; + } + + /** Copies directory from source to destination. */ + public static void copyDirectory(String source, String destination) throws IOException { + copyDirectory(Path.of(source), Path.of(destination)); + } + + /** Copies directory from source to destination. */ + public static void copyDirectory(Path source, Path destination) throws IOException { + try (Stream stream = Files.walk(source)) { + stream.forEach(src -> copy(src, destination.resolve(source.relativize(src)))); + } + } + + /** Copies from source to destination and replace existing. */ + private static void copy(Path source, Path destination) { + try { + Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + /** Initializes application directory. */ + private static String initApplicationDirectory() { + try { + Path path = Paths.get(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI()); + + if (path.toString().toLowerCase().endsWith(".jar")) { + return path.getParent().getParent().toString(); + } else { + return getProjectDirectory(); + } + + } catch (URISyntaxException e) { + Logger.getGlobal().severe(e.getMessage()); + } + + return ""; + } +} diff --git a/src/main/java/com/warxim/petep/util/GuiUtils.java b/src/main/java/com/warxim/petep/util/GuiUtils.java new file mode 100644 index 0000000..65be6ce --- /dev/null +++ b/src/main/java/com/warxim/petep/util/GuiUtils.java @@ -0,0 +1,87 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.util; + +import com.warxim.petep.extension.PetepAPI; +import javafx.scene.Node; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; + +/** GUI utils. */ +@PetepAPI +public final class GuiUtils { + private GuiUtils() {} + + /** + * Adds tab(node) to specified tab pane. (Wraps the node to a scroll pane, creates neww tab and + * adds it to the tabPane.) + */ + public static void addTabToTabPane(TabPane tabPane, String title, Node node) { + ScrollPane scrollPane = new ScrollPane(node); + + scrollPane.setFitToHeight(true); + scrollPane.setFitToWidth(true); + + tabPane.getTabs().add(new Tab(title, scrollPane)); + } + + /** Removes tab from specified tab pane. */ + public static void removeTabFromTabPane(TabPane tabPane, Node node) { + for (Tab tab : tabPane.getTabs()) { + Node content = tab.getContent(); + if (content instanceof ScrollPane && ((ScrollPane) content).getContent() == node) { + tabPane.getTabs().remove(tab); + break; + } + } + } + + /** Removes text formatting that has been done for JavaFx controls. */ + public static String unformatText(String text) { + char c = '\u2400'; + for (int i = 0; i < 9; ++i) { + text = text.replace(c++, (char) i); + } + + c = '\u240B'; + for (int i = 11; i < 32; ++i) { + text = text.replace(c++, (char) i); + } + + text = text.replace('\u2421', (char) 0x7F); + + return text; + } + + /** Formats text so it can be displayed inside JavaFX controls. */ + public static String formatText(String text) { + char c = '\u2400'; + for (int i = 0; i < 9; ++i) { + text = text.replace((char) i, c++); + } + + c = '\u240B'; + for (int i = 11; i < 32; ++i) { + text = text.replace((char) i, c++); + } + + text = text.replace((char) 0x7F, '\u2421'); + + return text; + } +} diff --git a/src/main/java/com/warxim/petep/util/PduUtils.java b/src/main/java/com/warxim/petep/util/PduUtils.java new file mode 100644 index 0000000..b5c6001 --- /dev/null +++ b/src/main/java/com/warxim/petep/util/PduUtils.java @@ -0,0 +1,234 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.util; + +import java.util.HashSet; +import java.util.Set; +import java.util.StringJoiner; +import com.warxim.petep.core.pdu.PDU; +import com.warxim.petep.extension.PetepAPI; + +/** PDU utils. */ +@PetepAPI +public final class PduUtils { + private PduUtils() {} + + /** Converts PDU buffer to string. */ + public static String bufferToString(PDU pdu) { + return BytesUtils.bytesToString(pdu.getBuffer(), pdu.getSize()); + } + + /** Converts tags to string. */ + public static String tagsToString(Set tags) { + if (tags.isEmpty()) { + return ""; + } + + StringJoiner joiner = new StringJoiner(","); + for (String tag : tags) { + joiner.add(tag); + } + + return joiner.toString(); + } + + /** Converts string to tags. */ + public static Set stringToTags(String str) { + Set tags = new HashSet<>(); + StringBuilder builder = new StringBuilder(); + + char[] arr = str.toCharArray(); + for (char c : arr) { + if (c == ',') { + if (builder.length() > 0) { + tags.add(builder.toString()); + } + builder.setLength(0); + } else { + builder.append(c); + } + } + + if (builder.length() > 0) { + tags.add(builder.toString()); + } + return tags; + } + + /** Replaces "what" bytes with "with" bytes for specified occurrence. */ + public static void replace(PDU pdu, byte[] what, byte[] with, int occurrence) { + byte[] buffer = pdu.getBuffer(); + int size = pdu.getSize(); + + if (what.length == with.length) { + int position = BytesUtils.findNth(buffer, size, 0, what, occurrence); + + // Not found? Return. + if (position == -1) { + return; + } + + // Replace specific number of bytes with "with". + System.arraycopy(with, 0, buffer, position, with.length); + + pdu.setBuffer(buffer, size); + } else { + int position = BytesUtils.findNth(buffer, size, 0, what, occurrence); + + if (position == -1) { + return; + } + + // Create new buffer if needed or use the old buffer. + byte[] newBuffer; + + int oldSize = size; + + size = size + (with.length - what.length); + + if (buffer.length < size) { + // Double the buffer or resize to size (prefers doubling the size). + if (buffer.length * 2 > size) { + newBuffer = new byte[buffer.length * 2]; + } else { + newBuffer = new byte[size]; + } + } else { + newBuffer = new byte[buffer.length]; + } + + // Add preceding bytes to the buffer. + System.arraycopy(buffer, 0, newBuffer, 0, position); + + // Add "with" to the buffer. + System.arraycopy(with, 0, newBuffer, position, with.length); + + // Add following bytes to the buffer. + int oldIndex = position + what.length; + + System.arraycopy(buffer, oldIndex, newBuffer, position + with.length, oldSize - oldIndex); + + pdu.setBuffer(newBuffer, size); + } + } + + /** Replaces all "what" bytes with "with" bytes. */ + public static void replace(PDU pdu, byte[] what, byte[] with) { + byte[] buffer = pdu.getBuffer(); + int size = pdu.getSize(); + int offset = 0; + + if (what.length == with.length) { + while (true) { + int position = BytesUtils.find(buffer, size, offset, what); + + if (position == -1) { + break; + } + + offset = position + with.length; + + System.arraycopy(with, 0, buffer, position, with.length); + } + + pdu.setBuffer(buffer, size); + } else { + while (true) { + int position = BytesUtils.find(buffer, size, offset, what); + + if (position == -1) { + break; + } + + // Move offset. + offset = position + with.length; + + byte[] newBuffer; + + int oldSize = size; + + // Create new buffer if needed. + size = size + (with.length - what.length); + + if (buffer.length < size) { + // Double the buffer or resize to size (prefers doubling the size). + if (buffer.length * 2 > size) { + newBuffer = new byte[buffer.length * 2]; + } else { + newBuffer = new byte[size]; + } + } else { + newBuffer = new byte[buffer.length]; + } + + // Add preceding bytes to the buffer. + System.arraycopy(buffer, 0, newBuffer, 0, position); + + // Add "with" to the buffer. + System.arraycopy(with, 0, newBuffer, position, with.length); + + // Add following bytes to the buffer. + int oldIndex = position + what.length; + + System.arraycopy(buffer, oldIndex, newBuffer, position + with.length, oldSize - oldIndex); + + // Set buffer to the new buffer. + buffer = newBuffer; + } + + pdu.setBuffer(buffer, size); + } + } + + /** + * Finds first occurrence of array inside of specified buffer, starting at specified offset. + * + * @return Returns index of the first occurrence or -1 if not found. + */ + public static int find(PDU pdu, int offset, byte[] array) { + return BytesUtils.find(pdu.getBuffer(), pdu.getSize(), offset, array); + } + + /** + * Finds specified occurrence of array inside of specified buffer, starting at specified offset. + * + * @return Returns index of the specified occurrence or -1 if not found. + */ + public static int findNth(PDU pdu, int offset, byte[] array, int n) { + return BytesUtils.findNth(pdu.getBuffer(), pdu.getSize(), offset, array, n); + } + + /** Returns true if the buffer contains specified "what" bytes. */ + public static boolean contains(PDU pdu, byte[] what) { + return BytesUtils.contains(pdu.getBuffer(), pdu.getSize(), what); + } + + /** Returns true if the buffer contains specified "what" bytes at specified position. */ + public static boolean containsAt(PDU pdu, byte[] what, int position) { + return BytesUtils.containsAt(pdu.getBuffer(), pdu.getSize(), what, position); + } + + /** Returns true if the buffer ends with "what" bytes. */ + public static boolean endsWith(PDU pdu, byte[] what) { + return BytesUtils.endsWith(pdu.getBuffer(), pdu.getSize(), what); + } + + /** Returns true if the buffer starts with "what" bytes. */ + public static boolean startsWith(PDU pdu, byte[] what) { + return BytesUtils.startsWith(pdu.getBuffer(), pdu.getSize(), what); + } +} diff --git a/src/main/java/com/warxim/petep/util/WebApiUtils.java b/src/main/java/com/warxim/petep/util/WebApiUtils.java new file mode 100644 index 0000000..309dbdf --- /dev/null +++ b/src/main/java/com/warxim/petep/util/WebApiUtils.java @@ -0,0 +1,87 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.warxim.petep.common.Constant; + +public class WebApiUtils { + private WebApiUtils() {} + + public static String getLatestVersion() { + try { + URL url = new URL(Constant.WEB + "api/version/"); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setRequestProperty("X-Requested-With", "XMLHttpRequest"); + connection.connect(); + + String data = convertStreamToString(connection.getInputStream()); + JsonObject object = new Gson().fromJson(data, JsonObject.class); + + if (!object.has("version")) { + logVersionFetchError(); + return Constant.VERSION; + } + + return object.get("version").getAsString(); + } catch (Exception e) { + logVersionFetchError(); + } + + return Constant.VERSION; + } + + private static String convertStreamToString(InputStream stream) { + BufferedReader reader = + new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)); + + StringBuilder builder = new StringBuilder(); + + String line; + try { + while ((line = reader.readLine()) != null) { + builder.append(line + "\n"); + } + } catch (IOException e) { + logVersionFetchError(); + } finally { + try { + stream.close(); + } catch (IOException e) { + logVersionFetchError(); + } + } + + return builder.toString(); + } + + private static void logVersionFetchError() { + Logger.getGlobal().log(Level.SEVERE, "Could not fetch latest PETEP version info."); + } +} diff --git a/src/main/java/com/warxim/petep/util/WebUtils.java b/src/main/java/com/warxim/petep/util/WebUtils.java new file mode 100644 index 0000000..2e0ad0d --- /dev/null +++ b/src/main/java/com/warxim/petep/util/WebUtils.java @@ -0,0 +1,54 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.util; + +import com.warxim.petep.extension.PetepAPI; + +/** Web utils. */ +@PetepAPI +public final class WebUtils { + private WebUtils() {} + + /** Converts value to JavaScript parameter wrapped in double quotes. */ + public static String toJavaScriptParam(String value) { + return "\"" + value.replace("\u0000", "\\0") + .replace("\\", "\\\\") + .replace("\"", "\\\"") + .replace("\n", "\\n") + .replace("\r", "\\r") + .replace("\t", "\\t") + "\""; + } + + /** Returns string with escaped HTML entities. */ + public static String escapeHtml(String value) { + StringBuilder out = new StringBuilder(Math.max(16, value.length())); + + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + + if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { + out.append("&#"); + out.append((int) c); + out.append(';'); + } else { + out.append(c); + } + } + + return out.toString(); + } +} diff --git a/src/main/java/com/warxim/petep/wizard/PetepWizard.java b/src/main/java/com/warxim/petep/wizard/PetepWizard.java new file mode 100644 index 0000000..f85d8f3 --- /dev/null +++ b/src/main/java/com/warxim/petep/wizard/PetepWizard.java @@ -0,0 +1,65 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.wizard; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.sun.javafx.css.StyleManager; +import com.warxim.petep.common.Constant; +import com.warxim.petep.gui.GuiBundle; +import com.warxim.petep.gui.PetepApplication; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.wizard.controller.WizardController; +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.stage.Stage; + +/** JavaFX Application class for GUI. */ +public final class PetepWizard extends PetepApplication { + @Override + public void start(Stage stage) { + // Load stylesheets. + Application.setUserAgentStylesheet(Application.STYLESHEET_MODENA); + StyleManager.getInstance() + .addUserAgentStylesheet(getClass().getResource("/css/Main.css").toString()); + + // Load wizard GUI. + try { + FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/wizard/Wizard.fxml")); + fxmlLoader.setController(new WizardController()); + Parent root = fxmlLoader.load(); + + Scene scene = new Scene(root); + scene.getStylesheets().add("/css/Main.css"); + + stage.getIcons().add(GuiBundle.getInstance().getPetepIcon()); + + stage.setTitle("PETEP Project Wizard v" + Constant.VERSION); + stage.setScene(scene); + stage.show(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Could not load PETEP gui. ", e); + } + + Dialogs.setDefaultIcon(GuiBundle.getInstance().getPetepIcon()); + + processVersionCheck(); + } +} diff --git a/src/main/java/com/warxim/petep/wizard/configuration/WizardConfigurationLoader.java b/src/main/java/com/warxim/petep/wizard/configuration/WizardConfigurationLoader.java new file mode 100644 index 0000000..bff419d --- /dev/null +++ b/src/main/java/com/warxim/petep/wizard/configuration/WizardConfigurationLoader.java @@ -0,0 +1,111 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.wizard.configuration; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.google.gson.JsonArray; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; +import com.warxim.petep.configuration.ProjectLoader; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.project.Project; +import com.warxim.petep.util.FileUtils; +import com.warxim.petep.wizard.project.WizardProjectDecorator; + +/** Static class for wizard configuration loading. */ +public final class WizardConfigurationLoader { + private WizardConfigurationLoader() {} + + /** + * Loads wizard configuration. + * + * @throws ConfigurationException + * @returns List of project decorators or empty list (if wizard configuration cannot be loaded) + */ + public static List load(String path) { + // Create configuration if not exist. + createIfNotExist(path); + + try (JsonReader reader = new JsonReader(new FileReader(path))) { + // Parse list from configuration. + + JsonArray list = JsonParser.parseReader(reader).getAsJsonArray(); + + List projects = new ArrayList<>(list.size()); + + for (int i = 0; i < list.size(); ++i) { + try { + String configFile = FileUtils.getApplicationFileAbsolutePath(list.get(i).getAsString() + + File.separator + com.warxim.petep.common.Constant.PROJECT_CONFIG_DIRECTORY + + File.separator + com.warxim.petep.common.Constant.PROJECT_CONFIG_FILE); + + // Load project information. + Project project = ProjectLoader.load(configFile); + + // Create project decorator with path and date and add it to list of projects. + projects.add(new WizardProjectDecorator(project, list.get(i).getAsString(), + new Date(new File(configFile).lastModified()))); + } catch (ConfigurationException e) { + Logger.getGlobal() + .log(Level.SEVERE, "PETEP wizard could not parse project configuration.", e); + } + } + + return projects; + + } catch (JsonParseException e) { + Logger.getGlobal().log(Level.SEVERE, "PETEP wizard configuration is invalid.", e); + } catch (NoSuchFileException e) { + Logger.getGlobal().info("PETEP wizard configuration doesn't exist."); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "PETEP wizard could not read configuration.", e); + } + + return new ArrayList<>(); + } + + /** + * Creates configuration with empty JSON array. + */ + private static void createIfNotExist(String pathInput) { + Path path = Paths.get(pathInput); + + if (Files.exists(path)) { + return; + } + + try { + Files.writeString(path, "[]", StandardOpenOption.CREATE); + } catch (IOException e) { + Logger.getGlobal() + .log(Level.SEVERE, "PETEP wizard could not create petep.json configuration.", e); + } + } +} diff --git a/src/main/java/com/warxim/petep/wizard/configuration/WizardConfigurationSaver.java b/src/main/java/com/warxim/petep/wizard/configuration/WizardConfigurationSaver.java new file mode 100644 index 0000000..f7b5e60 --- /dev/null +++ b/src/main/java/com/warxim/petep/wizard/configuration/WizardConfigurationSaver.java @@ -0,0 +1,61 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.wizard.configuration; + +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.NoSuchFileException; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.stream.JsonWriter; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.wizard.project.WizardProjectDecorator; + +/** Static class for wizard configuration saving. */ +public final class WizardConfigurationSaver { + private WizardConfigurationSaver() {} + + /** + * Save wizard configuration. + * + * @throws ConfigurationException + */ + public static void save(String path, Collection projects) { + // Gson with pretty printing. + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + JsonArray list = new JsonArray(projects.size()); + + // Create list of projects in json. + for (WizardProjectDecorator project : projects) { + list.add(project.getPath()); + } + + // Write project list to configuration. + try (JsonWriter writer = gson.newJsonWriter(new FileWriter(path))) { + gson.toJson(list, writer); + } catch (NoSuchFileException e) { + Logger.getGlobal().info("PETEP wizard configuration doesn't exist."); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "PETEP wizard could not save configuration.", e); + } + } +} diff --git a/src/main/java/com/warxim/petep/wizard/configuration/WizardExtensionsLoader.java b/src/main/java/com/warxim/petep/wizard/configuration/WizardExtensionsLoader.java new file mode 100644 index 0000000..b92bd0a --- /dev/null +++ b/src/main/java/com/warxim/petep/wizard/configuration/WizardExtensionsLoader.java @@ -0,0 +1,65 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.wizard.configuration; + +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.NoSuchFileException; +import java.util.ArrayList; +import java.util.List; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.wizard.project.WizardProjectExtension; + +/** Static class for project extension list loading. */ +public final class WizardExtensionsLoader { + private WizardExtensionsLoader() {} + + /** + * Loads project extensions from specified configuration. + * + * @throws ConfigurationException + */ + public static List load(String path) throws ConfigurationException { + try (JsonReader reader = new JsonReader(new FileReader(path))) { + // Parse array from configuration. + JsonArray list = JsonParser.parseReader(reader).getAsJsonArray(); + + List extensions = new ArrayList<>(list.size()); + + // Parse extensions. + for (int i = 0; i < list.size(); ++i) { + JsonObject object = list.get(i).getAsJsonObject(); + + extensions + .add(new WizardProjectExtension(object.get("path").getAsString(), object.get("store"))); + } + + return extensions; + } catch (JsonParseException e) { + throw new ConfigurationException("PETEP wizard configuration is invalid.", e); + } catch (NoSuchFileException e) { + throw new ConfigurationException("PETEP wizard configuration doesn't exist.", e); + } catch (IOException e) { + throw new ConfigurationException("PETEP wizard could not read configuration.", e); + } + } +} diff --git a/src/main/java/com/warxim/petep/wizard/configuration/WizardExtensionsSaver.java b/src/main/java/com/warxim/petep/wizard/configuration/WizardExtensionsSaver.java new file mode 100644 index 0000000..39789b0 --- /dev/null +++ b/src/main/java/com/warxim/petep/wizard/configuration/WizardExtensionsSaver.java @@ -0,0 +1,67 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.wizard.configuration; + +import java.io.FileWriter; +import java.io.IOException; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.stream.JsonWriter; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.wizard.project.WizardProjectExtension; + +/** Static class for project extension list saving. */ +public final class WizardExtensionsSaver { + private WizardExtensionsSaver() {} + + /** + * Save project extensions to specified configuration. + * + * @throws ConfigurationException + */ + public static void save(String path, Collection extensions) + throws ConfigurationException { + // Gson with pretty printing. + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + JsonArray list = new JsonArray(extensions.size()); + + // Construct list of extensions for JSON. + for (WizardProjectExtension extension : extensions) { + JsonObject object = new JsonObject(); + + object.addProperty("path", extension.getPath()); + object.add("store", extension.getStore()); + + list.add(object); + } + + // Write list of extensions to the configuration. + try (JsonWriter writer = gson.newJsonWriter(new FileWriter(path))) { + gson.toJson(list, writer); + } catch (IOException e) { + Logger.getGlobal() + .log(Level.SEVERE, "PETEP wizard could not save extensions configuration.", e); + throw new ConfigurationException("Project extensions could not be saved", e); + } + } +} diff --git a/src/main/java/com/warxim/petep/wizard/configuration/WizardProjectDirectoryCreator.java b/src/main/java/com/warxim/petep/wizard/configuration/WizardProjectDirectoryCreator.java new file mode 100644 index 0000000..c4e9ac6 --- /dev/null +++ b/src/main/java/com/warxim/petep/wizard/configuration/WizardProjectDirectoryCreator.java @@ -0,0 +1,32 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.wizard.configuration; + +import java.io.File; +import java.io.IOException; +import com.warxim.petep.util.FileUtils; + +/** Static class for project directory creation. */ +public final class WizardProjectDirectoryCreator { + private WizardProjectDirectoryCreator() {} + + /** Creates project directory from template (./project_template). */ + public static void create(String path) throws IOException { + FileUtils.copyDirectory( + new File(FileUtils.getApplicationDirectory(), "./project_template").getPath(), path); + } +} diff --git a/src/main/java/com/warxim/petep/wizard/controller/WizardController.java b/src/main/java/com/warxim/petep/wizard/controller/WizardController.java new file mode 100644 index 0000000..8d5f1fd --- /dev/null +++ b/src/main/java/com/warxim/petep/wizard/controller/WizardController.java @@ -0,0 +1,319 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.wizard.controller; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Path; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.warxim.petep.Main; +import com.warxim.petep.configuration.ModulesSaver; +import com.warxim.petep.configuration.ProjectLoader; +import com.warxim.petep.configuration.ProjectSaver; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.gui.dialog.AboutDialog; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.project.Project; +import com.warxim.petep.util.FileUtils; +import com.warxim.petep.wizard.configuration.WizardConfigurationLoader; +import com.warxim.petep.wizard.configuration.WizardConfigurationSaver; +import com.warxim.petep.wizard.configuration.WizardExtensionsSaver; +import com.warxim.petep.wizard.configuration.WizardProjectDirectoryCreator; +import com.warxim.petep.wizard.dialog.EditProjectDialog; +import com.warxim.petep.wizard.dialog.NewProjectDialog; +import com.warxim.petep.wizard.project.WizardProjectDecorator; +import com.warxim.petep.wizard.project.WizardProjectExtension; +import javafx.application.Platform; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.TableCell; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.stage.DirectoryChooser; +import javafx.stage.Stage; +import javafx.util.Pair; + +/** Wizard GUI controller. */ +public final class WizardController implements Initializable { + private static final String WIZARD_FILE = "petep.json"; + + // Columns. + @FXML + private TableColumn nameColumn; + @FXML + private TableColumn descriptionColumn; + @FXML + private TableColumn dateColumn; + @FXML + private TableColumn pathColumn; + + // Projects. + @FXML + private TableView projectsTable; + private ObservableList projects; + + /** Initializes wizard. */ + @Override + public void initialize(URL location, ResourceBundle resources) { + // Create observable list of projects. + projects = FXCollections.observableList(WizardConfigurationLoader.load(WIZARD_FILE)); + + // Initialize columns. + nameColumn.setCellValueFactory(new PropertyValueFactory<>("name")); + descriptionColumn.setCellValueFactory(new PropertyValueFactory<>("description")); + dateColumn.setCellValueFactory(new PropertyValueFactory<>("date")); + pathColumn.setCellValueFactory(new PropertyValueFactory<>("path")); + + dateColumn.setCellFactory(tc -> new TableCell() { + private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + + @Override + protected void updateItem(Date date, boolean empty) { + super.updateItem(date, empty); + + setText(empty ? null : format.format(date)); + } + }); + + // Bind projects to table. + projectsTable.setItems(projects); + } + + /** Handles new project button click. */ + @FXML + private void onNewButtonClick(ActionEvent event) { + DirectoryChooser directoryChooser = new DirectoryChooser(); + directoryChooser.setTitle("Save project"); + directoryChooser.setInitialDirectory(new File(System.getProperty("user.dir"))); + + // Do until the user enters correct values. + do { + // Choose project directory. + File directory = directoryChooser.showDialog(null); + if (directory == null) { + return; + } + + // Project directory must be empty (if it isn't, let user choose another one). + if (!FileUtils.isDirectoryEmpty(directory)) { + Dialogs.createErrorDialog("Directory is not empty!", + "Directory for new project has to be empty!"); + continue; + } + + try { + var project = showNewProjectDialog(directory.toPath()); + + if (project == null) { + return; + } + + createProject(directory.getPath(), project); + + return; + } catch (IOException | ConfigurationException e) { + Dialogs.createExceptionDialog("Exception occured", + "Exception occured during project creation!", e); + Logger.getGlobal().log(Level.SEVERE, "Exception during project creation", e); + } + + } while (true); + } + + /** Handles edit project button click. */ + @FXML + private void onEditButtonClick(ActionEvent event) { + WizardProjectDecorator project = projectsTable.getSelectionModel().getSelectedItem(); + + if (project == null) { + return; + } + + // Show edit project dialog. + try { + EditProjectDialog projectDialog = new EditProjectDialog(project); + + var data = projectDialog.showAndWait(); + + if (!data.isPresent() || data.get() == null) { + return; + } + + // Save project. + saveProject(project.getPath(), data.get().getKey().getProject(), data.get().getValue()); + + // Refresh projects table. + projectsTable.refresh(); + } catch (IOException e) { + Logger.getGlobal().log(Level.SEVERE, "Exception during openning of project dialog", e); + } catch (ConfigurationException e) { + Dialogs.createExceptionDialog("Project save error", "Project could not be saved!", e); + Logger.getGlobal().log(Level.SEVERE, "Exception during save", e); + } + } + + /** Saves project and its extension configuration. */ + private void saveProject(String path, Project project, List extensions) + throws ConfigurationException { + ProjectSaver.save(FileUtils.getApplicationFileAbsolutePath(path) + File.separator + + com.warxim.petep.common.Constant.PROJECT_CONFIG_DIRECTORY + File.separator + + com.warxim.petep.common.Constant.PROJECT_CONFIG_FILE, project); + + WizardExtensionsSaver.save(FileUtils.getApplicationFileAbsolutePath(path) + File.separator + + com.warxim.petep.common.Constant.PROJECT_CONFIG_DIRECTORY + File.separator + + com.warxim.petep.common.Constant.EXTENSIONS_CONFIG_FILE, extensions); + } + + /** Runs project in PETEP. */ + @FXML + private void onRunButtonClick(ActionEvent event) { + WizardProjectDecorator project = projectsTable.getSelectionModel().getSelectedItem(); + + if (project == null) { + return; + } + + // Run project. + new Thread(() -> Main.runPetep(project.getPath(), "--from-wizard")).start(); + + // Do not let JavaFX close our application, so we can start project GUI. + Platform.setImplicitExit(false); + + // Close wizard GUI + ((Stage) projectsTable.getScene().getWindow()).close(); + } + + /** Opens project from disk and adds it to Wizard. */ + @FXML + private void onOpenButtonClick(ActionEvent event) { + // Choose project directory. + DirectoryChooser directoryChooser = new DirectoryChooser(); + directoryChooser.setTitle("Open project"); + directoryChooser.setInitialDirectory(new File(System.getProperty("user.dir"))); + + File directory = directoryChooser.showDialog(null); + if (directory == null) { + return; + } + + // Load project. + try { + String configFile = directory.getPath() + File.separator + + com.warxim.petep.common.Constant.PROJECT_CONFIG_DIRECTORY + File.separator + + com.warxim.petep.common.Constant.PROJECT_CONFIG_FILE; + + Project project = ProjectLoader.load(configFile); + + // Add project to table. + projects.add( + new WizardProjectDecorator(project, FileUtils.applicationRelativize(directory.getPath()), + new Date(new File(configFile).lastModified()))); + + // Save wizard configuration. + WizardConfigurationSaver.save(WIZARD_FILE, projects); + } catch (ConfigurationException e) { + Dialogs.createExceptionDialog("Project could not be loaded", "Project could not be loaded!", + e); + Logger.getGlobal().log(Level.SEVERE, "Exception during load", e); + } + } + + /** Removes project from wizard. */ + @FXML + private void onRemoveButtonClick(ActionEvent event) { + WizardProjectDecorator project = projectsTable.getSelectionModel().getSelectedItem(); + + if (project == null) { + return; + } + + if (!Dialogs.createYesOrNoDialog("Are you sure?", "Do you really want to remove the project '" + + project.getName() + "' from the list? (Project will not be removed from the disk.)")) { + return; + } + + // Remove project from table. + projects.remove(project); + + // Save wizard configuration. + WizardConfigurationSaver.save(WIZARD_FILE, projects); + } + + /** Show about dialog on header click. */ + @FXML + private void onHeaderLabelClick() { + AboutDialog.show(); + } + + private Pair> showNewProjectDialog(Path path) + throws IOException { + NewProjectDialog projectDialog = new NewProjectDialog(FileUtils.applicationRelativize(path)); + + var data = projectDialog.showAndWait(); + + return data.isPresent() ? data.get() : null; + } + + private void createProject( + String path, + Pair> data) + throws ConfigurationException, IOException { + // Create project directory. + WizardProjectDirectoryCreator.create(path); + + // Save project. + saveProject(path, data.getKey().getProject(), data.getValue()); + + String configDirectory = path + File.separator + + com.warxim.petep.common.Constant.PROJECT_CONFIG_DIRECTORY + File.separator; + + // Create proxies.json if it does not exist. + String file = configDirectory + com.warxim.petep.common.Constant.PROXIES_CONFIG_FILE; + if (!new File(file).exists()) { + ModulesSaver.save(file, new ArrayList<>()); + } + + // Create interceptors-C2S.json if it does not exist. + file = configDirectory + com.warxim.petep.common.Constant.INTERCEPTORS_C2S_CONFIG_FILE; + if (!new File(file).exists()) { + ModulesSaver.save(file, new ArrayList<>()); + } + + // Create interceptors-S2C.json if it does not exist. + file = configDirectory + com.warxim.petep.common.Constant.INTERCEPTORS_S2C_CONFIG_FILE; + if (!new File(file).exists()) { + ModulesSaver.save(file, new ArrayList<>()); + } + + // Add project to table. + projects.add(data.getKey()); + + // Save wizard configuration. + WizardConfigurationSaver.save(WIZARD_FILE, projects); + } +} diff --git a/src/main/java/com/warxim/petep/wizard/dialog/EditProjectDialog.java b/src/main/java/com/warxim/petep/wizard/dialog/EditProjectDialog.java new file mode 100644 index 0000000..88520ff --- /dev/null +++ b/src/main/java/com/warxim/petep/wizard/dialog/EditProjectDialog.java @@ -0,0 +1,52 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.wizard.dialog; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import com.warxim.petep.exception.ConfigurationException; +import com.warxim.petep.util.FileUtils; +import com.warxim.petep.wizard.configuration.WizardExtensionsLoader; +import com.warxim.petep.wizard.project.WizardProjectDecorator; +import com.warxim.petep.wizard.project.WizardProjectExtension; +import javafx.collections.FXCollections; + +/** Edit project dialog. */ +public final class EditProjectDialog extends ProjectDialog { + public EditProjectDialog(WizardProjectDecorator project) + throws IOException, ConfigurationException { + super("Edit project", "Save"); + + // Store project + this.project = project; + + // Load extensions for the project + List list; + list = WizardExtensionsLoader.load(FileUtils.getApplicationFileAbsolutePath(project.getPath()) + + File.separator + com.warxim.petep.common.Constant.PROJECT_CONFIG_DIRECTORY + + File.separator + com.warxim.petep.common.Constant.EXTENSIONS_CONFIG_FILE); + + // Fill inputs + nameInput.setText(project.getName()); + descriptionInput.setText(project.getDescription()); + + extensions = FXCollections.observableArrayList(list); + + extensionsList.setItems(extensions); + } +} diff --git a/src/main/java/com/warxim/petep/wizard/dialog/NewProjectDialog.java b/src/main/java/com/warxim/petep/wizard/dialog/NewProjectDialog.java new file mode 100644 index 0000000..8e36571 --- /dev/null +++ b/src/main/java/com/warxim/petep/wizard/dialog/NewProjectDialog.java @@ -0,0 +1,46 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.wizard.dialog; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import com.warxim.petep.common.Constant; +import com.warxim.petep.wizard.project.WizardProjectDecorator; +import com.warxim.petep.wizard.project.WizardProjectExtension; +import javafx.collections.FXCollections; + +/** New project dialog. */ +public final class NewProjectDialog extends ProjectDialog { + public NewProjectDialog(String path) throws IOException { + super("New project", "Create"); + + // Create new project decorator for nonexisting (null) project. + this.project = new WizardProjectDecorator(null, path, null); + + // Initialize list of extensions. + List list = new ArrayList<>(Constant.INTERNAL_EXTENSIONS.size()); + + for (String extension : Constant.INTERNAL_EXTENSIONS) { + list.add(new WizardProjectExtension(extension, null)); + } + + extensions = FXCollections.observableArrayList(list); + + extensionsList.setItems(extensions); + } +} diff --git a/src/main/java/com/warxim/petep/wizard/dialog/ProjectDialog.java b/src/main/java/com/warxim/petep/wizard/dialog/ProjectDialog.java new file mode 100644 index 0000000..d433991 --- /dev/null +++ b/src/main/java/com/warxim/petep/wizard/dialog/ProjectDialog.java @@ -0,0 +1,143 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.wizard.dialog; + +import java.io.File; +import java.io.IOException; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import com.warxim.petep.common.Constant; +import com.warxim.petep.gui.dialog.Dialogs; +import com.warxim.petep.gui.dialog.SimpleInputDialog; +import com.warxim.petep.project.Project; +import com.warxim.petep.util.FileUtils; +import com.warxim.petep.wizard.project.WizardProjectDecorator; +import com.warxim.petep.wizard.project.WizardProjectExtension; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.ChoiceDialog; +import javafx.scene.control.ListView; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; +import javafx.stage.FileChooser; +import javafx.util.Pair; + +/** Project dialog. */ +public abstract class ProjectDialog + extends SimpleInputDialog>> { + // Project. + protected WizardProjectDecorator project; + + // Inputs. + @FXML + protected TextField nameInput; + @FXML + protected TextArea descriptionInput; + + // Extensions. + @FXML + protected ListView extensionsList; + protected ObservableList extensions; + + public ProjectDialog(String title, String okText) throws IOException { + super("/fxml/wizard/Project.fxml", title, okText); + } + + /** Handles add internal extension button click. */ + @FXML + protected final void onAddInternalButtonClick(ActionEvent event) { + if (Constant.INTERNAL_EXTENSIONS.isEmpty()) { + return; + } + + // Choose from internal extensions. + ChoiceDialog dialog = + new ChoiceDialog<>(Constant.INTERNAL_EXTENSIONS.get(0), Constant.INTERNAL_EXTENSIONS); + + dialog.setTitle("Add internal extension"); + dialog.setHeaderText("Add internal extension"); + dialog.setContentText("Extension:"); + + // Add extension to list. + Optional result = dialog.showAndWait(); + if (result.isPresent()) { + extensions.add(new WizardProjectExtension(result.get(), null)); + } + } + + /** Handles add external extension button click. */ + @FXML + protected final void onAddExternalButtonClick(ActionEvent event) { + // Choose extension file. + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Open project"); + fileChooser.setInitialDirectory(new File(System.getProperty("user.dir"))); + fileChooser.getExtensionFilters() + .add(new FileChooser.ExtensionFilter("PETEP jar extensions (*.jar)", "*.jar")); + + File file = fileChooser.showOpenDialog(null); + if (file == null) { + return; + } + + // Add extension to list. + extensions + .add(new WizardProjectExtension(FileUtils.applicationRelativize(file.getPath()), null)); + } + + /** Handles remove extension button click. */ + @FXML + protected final void onRemoveButtonClick(ActionEvent event) { + WizardProjectExtension extension = extensionsList.getSelectionModel().getSelectedItem(); + + if (extension == null) { + return; + } + + if (!Dialogs.createYesOrNoDialog("Are you sure?", + "Do you really want to remove the extension '" + extension.getPath() + + "' from the project? (Extension data stored in the configuration will be lost!)")) { + return; + } + + extensions.remove(extension); + } + + /** Checks if inputs are valid. */ + @Override + protected final boolean isValid() { + if (nameInput.getText().length() == 0) { + Dialogs.createErrorDialog("Project name required", "You have to enter project name."); + return false; + } + + return true; + } + + /** Obtains new project decorator and extensions. */ + @Override + protected final Pair> obtainResult() { + Project newProject = new Project(nameInput.getText(), descriptionInput.getText()); + + project.setProject(newProject); + project.setDate(new Date()); + + return new Pair<>(project, extensions); + } +} diff --git a/src/main/java/com/warxim/petep/wizard/project/WizardProjectDecorator.java b/src/main/java/com/warxim/petep/wizard/project/WizardProjectDecorator.java new file mode 100644 index 0000000..10dbb13 --- /dev/null +++ b/src/main/java/com/warxim/petep/wizard/project/WizardProjectDecorator.java @@ -0,0 +1,62 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.wizard.project; + +import java.util.Date; +import com.warxim.petep.project.Project; + +/** Project decorator (containing project, path to the project and date of project file changes). */ +public final class WizardProjectDecorator { + private String path; + private Date date; + private Project project; + + /** Project decorator constructor. */ + public WizardProjectDecorator(Project project, String path, Date date) { + this.project = project; + this.path = path; + this.date = date; + } + + public String getPath() { + return path; + } + + public Date getDate() { + return date; + } + + public String getName() { + return project.getName(); + } + + public String getDescription() { + return project.getDescription(); + } + + public Project getProject() { + return project; + } + + public void setProject(Project project) { + this.project = project; + } + + public void setDate(Date date) { + this.date = date; + } +} diff --git a/src/main/java/com/warxim/petep/wizard/project/WizardProjectExtension.java b/src/main/java/com/warxim/petep/wizard/project/WizardProjectExtension.java new file mode 100644 index 0000000..74410e8 --- /dev/null +++ b/src/main/java/com/warxim/petep/wizard/project/WizardProjectExtension.java @@ -0,0 +1,44 @@ +/* + * PEnetration TEsting Proxy (PETEP) + * + * Copyright (C) 2020 Michal Válka + * + * 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 . + */ +package com.warxim.petep.wizard.project; + +import com.google.gson.JsonElement; + +/** Project extension. */ +public final class WizardProjectExtension { + private final String path; + private final JsonElement store; + + /** Project extension constructor. */ + public WizardProjectExtension(String path, JsonElement store) { + this.path = path; + this.store = store; + } + + public String getPath() { + return path; + } + + /** Returns extension store. */ + public JsonElement getStore() { + return store; + } + + public String toString() { + return path; + } +} diff --git a/src/main/resources/LICENSE.txt b/src/main/resources/LICENSE.txt new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/src/main/resources/LICENSE.txt @@ -0,0 +1,674 @@ + 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/src/main/resources/css/Main.css b/src/main/resources/css/Main.css new file mode 100644 index 0000000..8699ccf --- /dev/null +++ b/src/main/resources/css/Main.css @@ -0,0 +1,480 @@ +/* * FONTS */ + @font-face { + src: url('../fonts/OpenSans-Regular.ttf'); +} + @font-face { + font-weight: bold; + src: url('../fonts/OpenSans-Bold.ttf'); +} + @font-face { + font-style: italic; + src: url('../fonts/OpenSans-ExtraBoldItalic.ttf'); +} +/* * COLORS */ + * { + -fx-color-light-1: #ffffff; + -fx-color-light-2: #f4f4fc; + -fx-color-light-3: #f05d5e; + -fx-color-dark-1: #272932; + -fx-color-dark-2: #383b53; + -fx-color-dark-3: #515477; + -fx-color-neutral-1: #8e96d9; + -fx-color-neutral-2: #bfc3df; + -fx-button-normal: -fx-color-neutral-2; + -fx-button-normal: -fx-color-neutral-2; + -fx-button-normal-hover: -fx-color-dark-2; + -fx-button-normal-text: -fx-color-dark-1; + -fx-button-normal-text-hover: -fx-color-light-1; + -fx-button-primary: -fx-color-dark-3; + -fx-button-primary-hover: -fx-color-dark-2; + -fx-button-primary-text: -fx-color-light-1; + -fx-button-primary-text-hover: -fx-color-light-1; + -fx-input-border: -fx-color-neutral-1; + -fx-input-border-hover: -fx-color-dark-3; + -fx-checkbox-background: -fx-color-neutral-2; + -fx-font-size: 11px; + -fx-font-family:'Open Sans'; + -fx-text-fill: -fx-color-dark-1; + -fx-focus-color: transparent; + -fx-faint-focus-color: transparent; +} + +/** ROOT */ +.root { + -fx-base: -fx-color-light-1; +} + +/* * MENU */ + .menu-bar, .menu, .menu-item-base, .menu-item, .menu-bar .label { + -fx-effect: null; + -fx-background-color: -fx-color-dark-3; + -fx-color: -fx-color-light-1; + -fx-text-fill: -fx-color-light-1; +} + .menu-bar > .container > .menu-button:hover, .menu-bar > .container > .menu-button:hover > .label, .menu-bar > .container > .menu-button:showing, .menu-bar > .container > .menu-button:showing > .label, .menu-bar > .container > .menu-button:focused, .menu-bar > .container > .menu-button:focused > .label, .menu-item:focused, .menu-item:focused > .label, .menu-item:hover, .menu-item:hover > .label { + -fx-background-color: -fx-color-light-3; +} + .menu-item:disabled .label { + -fx-opacity: 0.95; + -fx-text-fill: -fx-color-light-1; +} + .context-menu { + -fx-background-color: -fx-color-dark-3; +} + .context-menu .label { + -fx-text-fill: -fx-color-light-1; +} + .separator *.line { + -fx-border-style: solid; + -fx-border-width: 0 0 1 0; + -fx-border-color: -fx-color-light-1; +} +/* * TABS */ + .tab-pane .tab-header-area .tab-header-background { + -fx-background-color: -fx-color-dark-2; +} + .tab, .tab .tab-label { + -fx-background-color: -fx-color-dark-3; + -fx-text-fill: -fx-color-light-1; +} + .tab:hover, .tab:hover .tab-label { + -fx-background-color: -fx-color-light-3; +} + .tab:selected, .tab:selected .tab-label { + -fx-background-color: -fx-color-light-1; + -fx-text-fill: -fx-color-dark-1; + -fx-border-style: null; +} + .tab-pane:focused > .tab-header-area > .headers-region > .tab:selected .focus-indicator { + -fx-border-color: -fx-color-light-1; + -fx-border-style: null; +} + .tab-pane { + -fx-background-color: -fx-color-light-1; +} + .tab-header-area .tab{ + -fx-padding: 2 8 2 8; + -fx-background-radius: 0 0 0 0; + -fx-background-insets: 0 1 0 1; +} + .tab-pane:top *.tab-header-area { + -fx-padding:2 0 0 0 0; +} + +/* * SCROLL BAR */ + .scroll-bar:horizontal, .scroll-bar:vertical { + -fx-border-color: -fx-color-dark-3; +} + .scroll-bar:horizontal .track, .scroll-bar:vertical .track{ + -fx-background-color :transparent; + -fx-border-color :transparent; + -fx-background-radius : 0; + -fx-border-radius :0; + -fx-border :0; + -fx-background-color: -fx-color-light-1; +} + .scroll-pane > .corner { + -fx-background-color: -fx-color-light-1; +} + .scroll-bar:horizontal .increment-button , .scroll-bar:horizontal .decrement-button { + -fx-background-color :transparent; + -fx-background-radius : 0.0em; + -fx-padding: 0.25em; + -fx-border-color:-fx-color-light-1; +} + .scroll-bar:vertical .increment-button , .scroll-bar:vertical .decrement-button { + -fx-background-color :transparent; + -fx-background-radius : 0.0em; + -fx-padding: 0.25em; +} + .scroll-bar .increment-arrow, .scroll-bar .decrement-arrow{ + -fx-shape: ""; + -fx-padding: 0; +} + .scroll-bar:vertical .increment-arrow, .scroll-bar:vertical .decrement-arrow{ + -fx-shape: ""; + -fx-padding: 0; +} + .scroll-bar:horizontal .increment-arrow, .scroll-bar:horizontal .decrement-arrow{ + -fx-shape: ""; + -fx-padding: 0; +} + .scroll-bar:horizontal .thumb, .scroll-bar:vertical .thumb { + -fx-background-color: -fx-color-neutral-2; + -fx-background-insets : 2.0, 0.0, 0.0; + -fx-background-radius : 0em; +} + .scroll-bar:horizontal .thumb:hover, .scroll-bar:vertical .thumb:hover { + -fx-background-color: -fx-color-dark-3; + -fx-background-insets : 2.0, 0.0, 0.0; + -fx-background-radius : 0em; +} +/* * DIALOGS */ + .dialog-pane { + -fx-background-color: -fx-color-light-1; +} + .dialog-pane > .expandable-content { + -fx-background-color: -fx-color-light-1; +} + .dialog-pane:header .header-panel { + -fx-background-color: -fx-color-dark-3; +} + .dialog-pane:header .header-panel .label { + -fx-color: -fx-color-light-1; + -fx-text-fill: -fx-color-light-1; +} + .dialog-pane > .button-bar > .container { + -fx-background-color: -fx-color-light-1; +} + .dialog-pane > .content { + -fx-padding: 10px; +} + .simple-dialog > .content { + -fx-padding: 0; +} +/* * BUTTONS */ + .button { + -fx-padding: 4 10 4 10; + -fx-background-insets: 0,0 0 5 0, 0 0 6 0, 0 0 7 0; + -fx-background-radius: 0; + -fx-background-color: -fx-button-normal; + -fx-text-fill: -fx-button-normal-text; + -fx-effect: none; + -fx-font-weight: bold; + -fx-font-size: 1.1em; +} + .button:default, .button.is-primary { + -fx-background-color: -fx-button-primary; + -fx-text-fill: -fx-button-primary-text; + -fx-background-radius: 0; +} + .button:hover { + -fx-background-color: -fx-button-normal-hover; + -fx-text-fill: -fx-button-normal-text-hover; + -fx-cursor: hand; +} +/* * CHECKBOX */ + .check-box > .box, .check-box:focused > .box { + -fx-background-color: -fx-color-light-1; + -fx-border-color: -fx-input-border; +} + .check-box:selected > .mark { + -fx-background-insets: 0; + -fx-background-color: -fx-color-light-1; +} + .check-box:selected > .box { + -fx-background-insets: 0; + -fx-background-color: -fx-checkbox-background; + -fx-border-color: -fx-input-border-hover; +} + .check-box:hover > .box { + -fx-border-color: -fx-input-border-hover; +} + .check-box:selected > .box > .mark, .check-box:indeterminate > .box > .mark { + /* modify mark color */ + -fx-background-color: -fx-color-light-1; +} +/* * TEXT FIELD */ + .text-field, .text-area { + -fx-background-color: -fx-color-light-1; + -fx-border-color: -fx-input-border; +} + .text-area .content, .text-area:focused .content { + -fx-background-color: transparent; +} + .text-field:focused, .text-field:hover, .text-area:focused, .text-area:hover { + -fx-border-color: -fx-input-border-hover; + -fx-background-color: -fx-color-light-1; + -fx-effect: none; +} +/* * COMBO BOX */ + .combo-box .list-cell { + -fx-background: -fx-color-light-1 !important; + -fx-text-fill: -fx-color-dark-1; +} + .combo-box-popup .list-view { + -fx-background: -fx-color-light-1, -fx-color-light-1 !important; + -fx-background-insets: 0, 0; + -fx-effect: none; +} + .combo-box-popup .list-view .list-cell:filled:selected, .combo-box-popup .list-view .list-cell:filled:selected:hover { + -fx-background-color: -fx-color-light-1; + -fx-text-fill: -fx-selection-bar-text; +} + .combo-box-popup .list-view .list-cell:hover { + -fx-background-color: -fx-color-light-1; + -fx-text-fill: -fx-text-inner-color; +} + .combo-box .combo-box-popup .list-view, .combo-box .combo-box-popup .list-cell { + -fx-background-color: -fx-color-light-1; + -fx-text-fill: -fx-color-dark-1; +} + .combo-box-popup .list-view .list-cell:filled:hover { + -fx-background-color: -fx-color-light-1; + -fx-text-fill: -fx-text-inner-color; +} + .combo-box-popup .list-view .list-cell { + -fx-background-color: -fx-color-light-1; + -fx-text-fill: -fx-text-inner-color; +} + .combo-box-base { + -fx-background-color: -fx-color-light-1; + -fx-border-color: -fx-input-border; +} + .combo-box-base:hover { + -fx-color: -fx-hover-base; + -fx-background-color: -fx-color-light-1; + -fx-border-color: -fx-input-border-hover; +} + .combo-box-base:showing { + -fx-background-color: -fx-color-light-1; + -fx-border-color: -fx-input-border-hover; +} + .combo-box-base:focused { + -fx-background-color: -fx-color-light-1; + -fx-border-color: -fx-input-border-hover; +} + .combo-box-base:disabled { + -fx-opacity: .4; +} + .combo-box-popup > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:hover, .combo-box-popup > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected:hover , .combo-box-popup > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected { + -fx-background-color: -fx-color-dark-3; + -fx-text-fill: -fx-color-light-1; +} +/* * RADIO */ + .radio-button .radio { + -fx-background-color: #fff; + -fx-border-color: -fx-input-border; + -fx-background-image: null; + -fx-border-radius: 15px; + -fx-background-insets: 0; +} + .radio-button:selected .radio { + -fx-background-color: -fx-checkbox-background; + -fx-background-image: null; + -fx-border-color: -fx-input-border-hover; +} + .radio-button:hover .radio { + -fx-background-color: -fx-checkbox-background; + -fx-background-image: null; + -fx-border-color: -fx-input-border-hover; +} + .radio-button .dot { + -fx-background-insets: 0; + -fx-background-radius: 4px; + -fx-padding: 4px; + -fx-background-color: #fff; +} +/* * LIST VIEW */ + .list-view { + -fx-background-color: transparent; + -fx-border-style: solid; + -fx-border-color: -fx-color-dark-3; + -fx-padding:0; +} + .list-view .list-cell:odd { + -fx-background-color: -fx-color-light-2; + -fx-text-fill: -fx-color-dark-1; + -fx-border-style: none; + -fx-background-insets: 0; + -fx-background: -fx-accent; +} + .list-view:focused .list-cell:filled:focused { + -fx-background-color: -fx-color-neutral-2 !important; + -fx-text-fill: -fx-color-dark-1; + -fx-border-style: none; + -fx-background-insets: 0; + -fx-table-cell-border-color: -fx-color-neutral-1; +} +/* * TABLES */ + .table-view { + -fx-background-color: transparent; + -fx-border-style: solid; + -fx-border-color: -fx-color-dark-3; + -fx-padding:0; +} + .table-view .column-header-background { + -fx-background-color: -fx-color-dark-3; + -fx-background-insets: 0; + -fx-padding: 0; +} + .table-view .column-header-background .label { + -fx-background-color: -fx-color-dark-3; + -fx-text-fill: -fx-color-light-1; + -fx-font-weight: 400; + -fx-border-width:1px; + -fx-background-insets: 0; +} + .table-view .column-header-background .label .text { + -fx-font-size: 11px; +} + .table-view .filler { + -fx-background-color: -fx-color-dark-2; +} + .table-view .column-header { + -fx-background-color: -fx-color-dark-2; + -fx-border-style: none; + -fx-padding: 0; +} + .table-view .table-cell{ + -fx-text-fill: -fx-color-dark-1; + -fx-alignment: center; +} + .table-view .table-row-cell:odd { + -fx-background-color: -fx-color-light-2; + -fx-text-fill: -fx-color-dark-1; + -fx-border-style: none; + -fx-background-insets: 0; + -fx-background: -fx-accent; +} + .table-view:focused .table-row-cell:focused { + -fx-background-insets: 0, 0 0 0 0 !important; + -fx-border-width:0px; +} + .table-view .table-row-cell:selected { + -fx-background-color: -fx-color-neutral-2 !important; + -fx-text-fill: -fx-color-dark-1; + -fx-border-style: none; + -fx-background-insets: 0; + -fx-table-cell-border-color: -fx-color-light-1 !important; +} +/* * STYLES */ + .h1, .h1 .text { + -fx-font-size: 15px; + -fx-font-weight: 700; + -fx-text-fill: -fx-color-dark-3; +} + .h2, .h2 .text { + -fx-font-size: 13px; + -fx-font-weight: 700; + -fx-text-fill: -fx-color-dark-3; +} + .h3, .h3 .text { + -fx-font-size: 12px; + -fx-font-weight: 700; + -fx-text-fill: -fx-color-dark-3; +} +/* * HELPERs */ + .input-label { + -fx-font-weight: bold; +} + +.has-text-left { + -fx-alignment: center-left !important; +} + +/* * HEADERS */ + .header-1 { + -fx-background-color: -fx-color-dark-2; + -fx-color: -fx-color-light-1; + -fx-text-fill: -fx-color-light-1; + -fx-padding: 0 0 0 10px; + -fx-background-image: url("../img/Logo.png"); + -fx-background-size: contain ; + -fx-background-repeat: no-repeat; + -fx-background-position: right top; + -fx-pref-height:50px; +} + .header-1 .text { + -fx-font-size: 15px; + -fx-font-weight: 700; +} + .header-2 { + -fx-background-color: -fx-color-dark-3; + -fx-color: -fx-color-light-1; + -fx-text-fill: -fx-color-light-1; + -fx-padding: 0 0 0 10px; + -fx-pref-height:30px; +} + .header-2 .text { + -fx-font-size: 13px; + -fx-font-weight: 700; +} + + +/* + * LOG FLOW + */ +.log-flow { + -fx-padding: 5px; + -fx-border-style: solid; + -fx-border-width: 1; + -fx-border-color: -fx-color-neutral-1; +} + +.log-flow .log-record:info { + -fx-fill: -fx-color-dark-3; +} + +.log-flow .log-record:severe { + -fx-fill: #a93226; +} + +.log-flow .log-record:warning { + -fx-fill: #CA6F1E; +} + +.log-flow .log-record:fine { + -fx-fill: #229954; +} + +.log-flow .log-record:other { + -fx-fill: #344051; +} + +.log-flow .log-record:config { + -fx-fill: #2471A3; +} + +/* +* BYTES EDITOR +*/ +.bytes-editor { + -fx-font-family: "Monospaced"; +} + +.bytes-editor-charset { + -fx-font-family: "Monospaced"; + -fx-background-color: rgba(142, 150, 217, 0.3); + -fx-padding: 3; +} diff --git a/src/main/resources/css/guide/Main.css b/src/main/resources/css/guide/Main.css new file mode 100644 index 0000000..154361b --- /dev/null +++ b/src/main/resources/css/guide/Main.css @@ -0,0 +1,66 @@ +/* * FONTS */ + @font-face { + src: url('../fonts/OpenSans-Regular.ttf'); +} + @font-face { + font-weight: bold; + src: url('../fonts/OpenSans-Bold.ttf'); +} + @font-face { + font-style: italic; + src: url('../fonts/OpenSans-ExtraBoldItalic.ttf'); +} + +/* * COLORS */ + body { + font-size: 11px; + font-family:'Open Sans'; + color: #272932; + } + + h1 { + font-size: 15px; + font-weight: 700; + color: #515477; +} + +h2 { + font-size: 13px; + font-weight: 700; + color: #515477; +} + + h3 { + font-size: 12px; + font-weight: 700; + color: #515477; +} + + h3 { + font-size: 11px; + font-weight: 700; + color: #515477; +} + +ul { + list-style: none; +} + + +li::before { + content: "▪"; + color: #515477; + font-weight: bold; + display: inline-block; + width: 1em; + margin-left: -1em; +} + +a { + text-decoration:none; +} + +.code { + background:#f4f4fc; + padding:5px; +} \ No newline at end of file diff --git a/src/main/resources/fonts/OpenSans-Bold.ttf b/src/main/resources/fonts/OpenSans-Bold.ttf new file mode 100644 index 0000000..7b52945 Binary files /dev/null and b/src/main/resources/fonts/OpenSans-Bold.ttf differ diff --git a/src/main/resources/fonts/OpenSans-BoldItalic.ttf b/src/main/resources/fonts/OpenSans-BoldItalic.ttf new file mode 100644 index 0000000..a670e14 Binary files /dev/null and b/src/main/resources/fonts/OpenSans-BoldItalic.ttf differ diff --git a/src/main/resources/fonts/OpenSans-ExtraBold.ttf b/src/main/resources/fonts/OpenSans-ExtraBold.ttf new file mode 100644 index 0000000..3660681 Binary files /dev/null and b/src/main/resources/fonts/OpenSans-ExtraBold.ttf differ diff --git a/src/main/resources/fonts/OpenSans-ExtraBoldItalic.ttf b/src/main/resources/fonts/OpenSans-ExtraBoldItalic.ttf new file mode 100644 index 0000000..8c4c15d Binary files /dev/null and b/src/main/resources/fonts/OpenSans-ExtraBoldItalic.ttf differ diff --git a/src/main/resources/fonts/OpenSans-Italic.ttf b/src/main/resources/fonts/OpenSans-Italic.ttf new file mode 100644 index 0000000..e6c5414 Binary files /dev/null and b/src/main/resources/fonts/OpenSans-Italic.ttf differ diff --git a/src/main/resources/fonts/OpenSans-Light.ttf b/src/main/resources/fonts/OpenSans-Light.ttf new file mode 100644 index 0000000..563872c Binary files /dev/null and b/src/main/resources/fonts/OpenSans-Light.ttf differ diff --git a/src/main/resources/fonts/OpenSans-LightItalic.ttf b/src/main/resources/fonts/OpenSans-LightItalic.ttf new file mode 100644 index 0000000..5ebe2a2 Binary files /dev/null and b/src/main/resources/fonts/OpenSans-LightItalic.ttf differ diff --git a/src/main/resources/fonts/OpenSans-Regular.ttf b/src/main/resources/fonts/OpenSans-Regular.ttf new file mode 100644 index 0000000..2e31d02 Binary files /dev/null and b/src/main/resources/fonts/OpenSans-Regular.ttf differ diff --git a/src/main/resources/fonts/OpenSans-SemiBold.ttf b/src/main/resources/fonts/OpenSans-SemiBold.ttf new file mode 100644 index 0000000..99db86a Binary files /dev/null and b/src/main/resources/fonts/OpenSans-SemiBold.ttf differ diff --git a/src/main/resources/fonts/OpenSans-SemiBoldItalic.ttf b/src/main/resources/fonts/OpenSans-SemiBoldItalic.ttf new file mode 100644 index 0000000..8cad4e3 Binary files /dev/null and b/src/main/resources/fonts/OpenSans-SemiBoldItalic.ttf differ diff --git a/src/main/resources/fxml/Application.fxml b/src/main/resources/fxml/Application.fxml new file mode 100644 index 0000000..4035a75 --- /dev/null +++ b/src/main/resources/fxml/Application.fxml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/fxml/control/BytesEditor.fxml b/src/main/resources/fxml/control/BytesEditor.fxml new file mode 100644 index 0000000..d351f6e --- /dev/null +++ b/src/main/resources/fxml/control/BytesEditor.fxml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + diff --git a/src/main/resources/fxml/control/PduEditor.fxml b/src/main/resources/fxml/control/PduEditor.fxml new file mode 100644 index 0000000..849c4b2 --- /dev/null +++ b/src/main/resources/fxml/control/PduEditor.fxml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + +