commit 355ec190ce61869df91b7cc8b7e0947dee65d810 Author: Ulf Frisk Date: Sun Feb 2 00:58:44 2025 +0100 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..61f2fc2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.vs/ +x64/ +build/ +Debug/ +Release/ diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..0e09a3e --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,610 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +----------------------------------------------------------- + +BSD 3-Clause License + +Copyright 2016, Google Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from this +software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +----------------------------------------------------------- + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..bb8adcf --- /dev/null +++ b/Readme.md @@ -0,0 +1,104 @@ +libleechgrpc +============ + +libleechgrpc is a wrapper around gRPC to allow PCILeech/LeechCore/MemProcFS to access remote LeechAgent instances in a platform independent way. + +libleechgrpc supports two authentication modes: +* unauthenticated with no transport encryption - i.e. insecure mode. +* mutually authenticated mTLS connection - i.e. secure mode. + +libleechgrpc is by default statically linked and shouldn't require additional libraries. + + + +Building (Windows): +=================== +``` +# +# Install grpc-static via vcpkg +# This will take a decent while since it's compiling etc. +# +git clone https://github.com/microsoft/vcpkg.git C:\src\vcpkg +cd C:\src\vcpkg +.\bootstrap-vcpkg.bat +.\vcpkg integrate install +.\vcpkg install grpc:x64-windows-static protobuf:x64-windows-static + +# +# Generate gRPC stubs using the installed packages. +# +cd C:\src\leechgrpc\leechgrpc\ +C:\src\vcpkg\installed\x64-windows-static\tools\protobuf\protoc.exe --proto_path=proto --cpp_out=generated --grpc_out=generated --plugin=protoc-gen-grpc="C:\src\vcpkg\installed\x64-windows\tools\grpc\grpc_cpp_plugin.exe" leechgrpc.proto + +# +# Build leechgrpc in Visual Studio or by using the Visual Studio 2022 command prompt: +# +cd C:\src\leechgrpc\ +MSBuild libleechgrpc.sln /t:Rebuild /property:Configuration=Release /property:Platform=x64" +``` + + + +Building (Linux): +=================== +```bash +# export local bin directory to path +export MY_INSTALL_DIR=$HOME/.local +export PATH="$MY_INSTALL_DIR/bin:$PATH" + +# install build tools +sudo apt update +sudo apt install git build-essential autoconf libtool pkg-config + +# clone gRPC from github +mkdir -p $HOME/.local +mkdir -p $HOME/.local/build +cd $HOME/.local/build +git clone --recurse-submodules -b v1.66.0 https://github.com/grpc/grpc.git +cd grpc +git submodule update --init --recursive +mkdir -p cmake/build +cd cmake/build + +# get cmake (since linux cmake may be too old) +wget -q -O cmake-linux.sh https://github.com/Kitware/CMake/releases/download/v3.30.3/cmake-3.30.3-linux-x86_64.sh +sh cmake-linux.sh -- --skip-license --prefix=$MY_INSTALL_DIR +rm cmake-linux.sh +export PATH="$HOME/.local/bin:$PATH" +cmake --version + +# build gRPC as a static library and install locally +cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE \ + -DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR \ + -DBUILD_SHARED_LIBS=OFF \ + -DgRPC_INSTALL=ON \ + -DgRPC_BUILD_TESTS=OFF \ + -DgRPC_BUILD_GRPC_CSHARP_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_NODE_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_PHP_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_PYTHON_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_RUBY_PLUGIN=OFF \ + ../.. +make -j 4 +make install + +# clone libleechgrpc from github +mkdir -p ~/Github/ +cd ~/Github/ +git clone https://github.com/ufrisk/libleechgrpc +mkdir -p ~/Github/libleechgrpc/libleechgrpc/build +cd ~/Github/libleechgrpc/libleechgrpc/build + +# build libleechgrpc.so +cmake \ + -DCMAKE_PREFIX_PATH="$MY_INSTALL_DIR" \ + -DCMAKE_CXX_FLAGS="-DLINUX -fPIC -O2 -ffunction-sections -fdata-sections -flto" \ + -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS="-flto -Wl,--gc-sections" \ + .. +make -j 4 + +# libleechgrpc.so should now have been built if everything was successful! +``` diff --git a/cert/client-tls.cer b/cert/client-tls.cer new file mode 100644 index 0000000..88737d5 --- /dev/null +++ b/cert/client-tls.cer @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCTCCAfGgAwIBAgIULquEzhPTDxOYReDVDTwZdg6EaMUwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDEyNzE2MDkwMloXDTI2MDEy +NzE2MDkwMlowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAnL8Nqmwv/XK+UB+jE49vRYI3ZY7by6GeKaSd57z+ukiN +nDVRlivmIrRGQsjoEpM0w9ZNlDdGcT2jT1JfAitFRGEXN0mmYGgX8KcCZ/AUouWZ +oEqApqrvqSh7Wx+I+OHQpiIhybV8CvYPQxacWrpr484jSfEmaMcxxOv1rK3qTfUP +VI4nLVfOdlTvRpJymxFoJItVWZtUo1AK/kWGrCG0ESvz9/XWZYBmui891P1aunIX +Yq3LDA3ClYr6sa7Perdvj+MWKR85PkJuwE0dz5IKm8m48C9pmmWmChxY2krNtyOJ +IO6I6nZOufIbdyNmg+kchkaBzhf4ilUfGdaXctYCgQIDAQABo1MwUTAdBgNVHQ4E +FgQUN2iRFkdh9cPtBE4fQK7UYaaXBxYwHwYDVR0jBBgwFoAUN2iRFkdh9cPtBE4f +QK7UYaaXBxYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAipsu +E1gQAtrMoWm3wPngsvxX/bi8M6ND9RnLi2O4C/0lnbNkRvIXqnuw8gvaRuXcdIJx +ftJO202df4JaPnZrdmpmwto4Bi3z2pnZYh4BPTMBuQNKdGtieF/WEfYtrXoD/D0U +IYnraCKKRUZ3OOjegS3gqAg2eqRmHd9YmsT3ROGdI1OD8Zw88xlQGE9CoW9hvjCx +lxGrgP1eSFyiQK5yY8RB0dgknm1Yz3XEeu2b7mO7pXpJcmDyNqhjRmUSNWtfl/24 +BIHOkPqDRIQyeqRw4VkbLLTTh1RhogSckOnRnYiYPDwFnHuOoK14iw1K2XxxdJfL +SUEGXxqzige7f4LEVQ== +-----END CERTIFICATE----- diff --git a/cert/client-tls.key b/cert/client-tls.key new file mode 100644 index 0000000..fa05067 --- /dev/null +++ b/cert/client-tls.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCcvw2qbC/9cr5Q +H6MTj29FgjdljtvLoZ4ppJ3nvP66SI2cNVGWK+YitEZCyOgSkzTD1k2UN0ZxPaNP +Ul8CK0VEYRc3SaZgaBfwpwJn8BSi5ZmgSoCmqu+pKHtbH4j44dCmIiHJtXwK9g9D +FpxaumvjziNJ8SZoxzHE6/WsrepN9Q9UjictV852VO9GknKbEWgki1VZm1SjUAr+ +RYasIbQRK/P39dZlgGa6Lz3U/Vq6chdircsMDcKVivqxrs96t2+P4xYpHzk+Qm7A +TR3PkgqbybjwL2maZaYKHFjaSs23I4kg7ojqdk658ht3I2aD6RyGRoHOF/iKVR8Z +1pdy1gKBAgMBAAECggEAALamqvX8O6/LFZmoRA93BOKqaoMdhWI0YmmEObzgrrPD +98AfIYMshG/MQlNwaX27q7DI+H3OK3epq7Oy+KM+aOjVeogieo28vqje9B7J1EI9 +6lauelu8tKkZUyVMCgB6ovf0rgquQG1FbWNv5aKTuUUr4FM5fth5xbUCgLVHs9BB +/PHGqH/YgG7DjCImxR7ZxkrxLuRdGtgGN/Tv9FOvF/iAtOW4KGGdPyDlmr+DL491 +yZoSRsj3vXiXwTVKJsA+Hr+OB/2PPN7LnFWTIWERmxVQJi+nUyP69VaSPlvz6JQ+ +hiNarYQK82LWTSWPNHXB/NOJrvvLCk7hmQIBVdvtsQKBgQDQeC20ezGFsEnINgJm +yKX/LI54Ascz2fOMMmus522MdUYweyasVD3Qk/zKU0FCxgGapDTacfQFfeSutzOy +0LGZFhz2h/260Ws2Joz23yzDcMrlqMaIe4d2gJ1xiTTATmMkZtpYVdRYBePg+4hW +62bKbe+2IIfyOhqg/KLl/jvMUQKBgQDAe+3Lp5SA2fuCHi0eahpnZcDr2w1ptogn +fqTGSWKk3/wjXYzFQSMnZir09u8oQELrtyNjnIThPcQ+9H1FSN+ZcmIRpTyLaVN0 +xm4sqfZ7HfpjgRNgMpyqhF/+R1EkmxdNEUlkjqaa4zjQkUlXV7/+B8wxuiIbJOe1 +E/EozXa3MQKBgCPwM+DjQ/xKEc4kEXHqsUM2STFDOVglAKlwn8Nk+iu2o+0Drf0T +YLyuZmvywlNikzA3kqz97BVuSJgeGRmAhL1hZIjTlNg59gOVzcNZYfwnW7MPz3oD +4ax6K6pA/wkP+mNyH74OvdaW3VwRwMVLO6M2JJb/MLB/d8u9AdAobeKhAoGBAJz7 +9gMk178HCVMj3VRy4Ln3iRJTA2t2TTE43pZBf8xMSU1mnMq7xzn434wOYRsI3gt0 +v84b91vkjktyB0EcoBB783PEuc5Rxpj0xSJ0M+xRlMbWnMDWRmPjto6iB5G9U5Gt +SZhTp5mnO80O0SwFCzbZkTX1Qp+0x60taIAIoovhAoGBAM5xOExRJwIvCo0kJF3f +EWgcEQmlxk7wACzRo/afrzze79uYN1HrNjqgOcu9XVKLw8nunp971jHuWMldrPfx +dgu3sDaVWB7+sjyr5q9/Lu5Pq/yHvMLfL5FPhXJNnnvltmK5LuIVGc6pUzGVpUgF +tNfWTpKxshYnZ20YsiBqmBtJ +-----END PRIVATE KEY----- diff --git a/cert/client-tls.p12 b/cert/client-tls.p12 new file mode 100644 index 0000000..bd6ed9e Binary files /dev/null and b/cert/client-tls.p12 differ diff --git a/cert/password.txt b/cert/password.txt new file mode 100644 index 0000000..992a64a --- /dev/null +++ b/cert/password.txt @@ -0,0 +1,5 @@ +test + + +openssl req -x509 -newkey rsa:2048 -keyout client-tls.key -out client-tls.crt -days 365 -nodes -subj "/CN=localhost" +openssl pkcs12 -export -out client-tls.p12 -inkey client-tls.key -in client-tls.crt -password pass:test \ No newline at end of file diff --git a/cert/readme.txt b/cert/readme.txt new file mode 100644 index 0000000..6821d57 --- /dev/null +++ b/cert/readme.txt @@ -0,0 +1,9 @@ +These certificates are only for use in testing mTLS connections with the leechgrpc_test_server & leechgrpc_test_client projects. + +Do not under any circumstances use these certificates / keys in any production environment! + +Password to the .pfx files: test + +Generated with commands: +openssl req -x509 -newkey rsa:2048 -keyout client-tls.key -out client-tls.crt -days 365 -nodes -subj "/CN=localhost" +openssl pkcs12 -export -out client-tls.p12 -inkey client-tls.key -in client-tls.crt -password pass:test diff --git a/cert/server-tls.cer b/cert/server-tls.cer new file mode 100644 index 0000000..c9ea248 --- /dev/null +++ b/cert/server-tls.cer @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCTCCAfGgAwIBAgIUa7SPVgJaTd5awjxOGkvu9CcPFPcwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDEyNzE2MDgzNFoXDTI2MDEy +NzE2MDgzNFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtIaZ/3JlzIM+NmUsdSX/01Sw0yiy/tXnaDdI1CdUVgWx +83iKPjSYBNntR4UMafiealWn2pr059K4dbLIor2i8Qx2v5riM9k7gyw3bZkdJOdj +mg7wtQFqvd/Z4kJiTf5ORJO7rRoeK0fxQJkxYm2f54v2gRmiiBoJjA5k7bY8R2dz +ZLqJc+bF2zZH8+JUKmkfNbPyPx5LrMTGu/78l+nkdi6OHp9Axd4RFQMMVQ1Sbzkc +DfZxEiWT3bNPqJh5de5/C8EwcxVdjIcAzGqMm1vh7fMAEHllhghJ6npmT7Dc5mVT +eRKiHPitIlA+CQ+R6jUTLEYjXl8THELDXuV2BVL8oQIDAQABo1MwUTAdBgNVHQ4E +FgQUDi7jUZuPjEbcflXQqALNO52cdw0wHwYDVR0jBBgwFoAUDi7jUZuPjEbcflXQ +qALNO52cdw0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEABzPJ +5KTVhT9UteUzAvgjGWQ/6GmsL8oT9XL/au6n/OWLCS1L4h47QPqjaOjZ9SDl+iyF +Myz8NdSUwSNxHDywOKswwFtUWRibRiOjKwWSHLjLtU1BlUTorh3ZCrRz74apdlFC +KQtngMe7cC08DtGtamSxGQ2wpvQ/nISEF3t6VGu5z9pkK6uqkKKxZZoJcVAW/Bsg ++CukowSkNberKPMoKlm1gjFCy8z94nSNTuIIsjMjWtnh5TivHEZfxU5qjo6vLPVG +9EGdNXPChG7Imo4a8rSue40aDgVOnA2P5KVoT5ArVIuS8XCCID8cB4hbT0uv2yjc +tEYT2+hYmdkpJWBfiA== +-----END CERTIFICATE----- diff --git a/cert/server-tls.key b/cert/server-tls.key new file mode 100644 index 0000000..ecbf7e8 --- /dev/null +++ b/cert/server-tls.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC0hpn/cmXMgz42 +ZSx1Jf/TVLDTKLL+1edoN0jUJ1RWBbHzeIo+NJgE2e1HhQxp+J5qVafamvTn0rh1 +ssiivaLxDHa/muIz2TuDLDdtmR0k52OaDvC1AWq939niQmJN/k5Ek7utGh4rR/FA +mTFibZ/ni/aBGaKIGgmMDmTttjxHZ3Nkuolz5sXbNkfz4lQqaR81s/I/HkusxMa7 +/vyX6eR2Lo4en0DF3hEVAwxVDVJvORwN9nESJZPds0+omHl17n8LwTBzFV2MhwDM +aoybW+Ht8wAQeWWGCEnqemZPsNzmZVN5EqIc+K0iUD4JD5HqNRMsRiNeXxMcQsNe +5XYFUvyhAgMBAAECggEAA8v06dobvqe1TkA7JXeYICIJhKy4HwNGq6Vwra2UvikT +1ggJ+Ebzj4k5zqWYs5MxWbvVcj6MugzE07eKirRW/J+De9d5EcLBgqpnvAawBeUB +Q5iJgspggVUiPaT3G6bROetVfiLXfEI2FmK3wYHcDsBIfeyZGNMGB7ZhybIUeyKZ +G61Qq8WtuCp3odXbaM53SfMeqjtMJTodbc7xphR7h+9YLVvrmUubbk0GzCbUHc1o +0G4OHRPMIDs6G1lRYID6ChwZFLwg+u5htQ2jodSw5Mp8WhaD+NiKiMabsIzM2a2F +nhvv6zeyQJ3hB2mKwQWNSCQj+MxRlVPp2uFSP7bNcQKBgQDrqNyop3D7NPeVfxwp +MxtLBqpgjE6OFCILvear5QzGmM8nONoMuCjZJvgs2VGRjIQeS0W9czJN4Oy0YWFw +FiqeMWSmn9xdWb6WrJttYZe79oUNU6Pw9Y6368ENI0BlFmo5xsZJZxVoiAwMTScP +Oh1wYsi6pIioRhC0DZp8DL3FlQKBgQDEG4Bz0ee9TjxCGCCDANyDzwALaUTOJxr2 +cN6nTpsxOiNEGNQR1sFHrBWwZfLN1N19cyjUt+qxJjC4ZJsC2D0+8N8Sfh5eyVgN +XQlAoccb+Ki8lUwwRZd24ZmAdRfck2zWSFQEq0+GK2wRjGD1HhzHrkttIgp5oxbJ +Boi9OvD/3QKBgC400981xY9b2Ve0rp7daHKTggCgQh7Vj79hosL9jD28ZJG6Mfbg +fRHm9C5HBhlVxenytF/rIGfovEC5/1Ls5bpS0PtiyOB84kPE4EzYH9o5AemVBsYO +P8eMMDQVP2ESvg1KDkMCNU5jrokS75+qs27/z3/ZFvp3knrbV/kOvn7pAoGAO4tK +LmCOp6konLzsqjpJum/QyKY28Q1on2lYAZ7ZelH3wUZ0pdH6L8PtdfkOhzbZ5axg +um35gb5hzqslcfCsb/79DIVkvU0PQkd8drZoWXLf8Rq33nRS8BLB5AIps5zD0DB3 +6k8Fv2xRzOY9zk9NV8fxOPq8CYDeez1TqXlLEbUCgYEAuSfPfHYCT388zfceAWNO +VtN8c4uFNLZEC++7K+H3rEY6ADfW7Vgk54bn0IQNqkL3wFs+64HjU2HfBiHPFegW +ZEPhBiO5+EsmlAHexuNwUV6A74CZYgPnbcQC1x8nK69uNJHrTDCd55qfmCYkDDXw +BDXN+at1hbwGUqm+qDb5TCo= +-----END PRIVATE KEY----- diff --git a/cert/server-tls.p12 b/cert/server-tls.p12 new file mode 100644 index 0000000..fcf9868 Binary files /dev/null and b/cert/server-tls.p12 differ diff --git a/leechgrpc_test_client/leechgrpc_test_client.cc b/leechgrpc_test_client/leechgrpc_test_client.cc new file mode 100644 index 0000000..ffbb487 --- /dev/null +++ b/leechgrpc_test_client/leechgrpc_test_client.cc @@ -0,0 +1,79 @@ +#include +#include +#include "../libleechgrpc/leechgrpc.h" + +#pragma comment(lib, "libleechgrpc.lib") + +int main_insecure() +{ + LPCSTR szHOST = "localhost"; + DWORD dwPORT = 28474; + HANDLE hGRPC; + PBYTE pbIn = NULL, pbOut = NULL; + SIZE_T cbIn = 0, cbOut = 0; + BOOL fResult; + + hGRPC = leechgrpc_client_create_insecure(szHOST, dwPORT); + + if(hGRPC == NULL) { + printf("[Client] Error creating gRPC client.\n"); + return 1; + } + + pbIn = (PBYTE)"MESSAGE FROM TEST CLIENT!"; + cbIn = strlen((char *)pbIn); + + fResult = leechgrpc_client_submit_command(hGRPC, pbIn, cbIn, &pbOut, &cbOut); + + if(!fResult) { + printf("[Client] Error submitting command.\n"); + leechgrpc_client_free(hGRPC); + return 1; + } + + printf("[Client] Server responded with: %s\n", pbOut); + + leechgrpc_client_free(hGRPC); + + return 0; +} + +int main_secure_tls() +{ + LPCSTR szHOST = "127.0.0.1"; + DWORD dwPORT = 28474; + HANDLE hGRPC; + PBYTE pbIn = NULL, pbOut = NULL; + SIZE_T cbIn = 0, cbOut = 0; + BOOL fResult; + + hGRPC = leechgrpc_client_create_secure_p12(szHOST, dwPORT, "localhost", "..\\..\\cert\\server-tls.cer", "..\\..\\cert\\client-tls.p12", "test"); + + if(hGRPC == NULL) { + printf("[Client] Error creating gRPC client.\n"); + return 1; + } + + pbIn = (PBYTE)"MESSAGE FROM TEST CLIENT!"; + cbIn = strlen((char *)pbIn); + + fResult = leechgrpc_client_submit_command(hGRPC, pbIn, cbIn, &pbOut, &cbOut); + + if(!fResult) { + printf("[Client] Error submitting command.\n"); + leechgrpc_client_free(hGRPC); + return 1; + } + + printf("[Client] Server responded with: %s\n", pbOut); + + leechgrpc_client_free(hGRPC); + + return 0; +} + +int main() +{ + //main_insecure(); + main_secure_tls(); +} diff --git a/leechgrpc_test_client/leechgrpc_test_client.vcxproj b/leechgrpc_test_client/leechgrpc_test_client.vcxproj new file mode 100644 index 0000000..f51026e --- /dev/null +++ b/leechgrpc_test_client/leechgrpc_test_client.vcxproj @@ -0,0 +1,156 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {6126530e-8882-4aaf-97e0-177c0ddb7ede} + leechgrpctestclient + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + $(VC_IncludePath);$(WindowsSDK_IncludePath); + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(SolutionDir)$(Platform)\$(Configuration)\; + + + $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Platform)\$(Configuration)\; + + + $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Platform)\$(Configuration)\; + + + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(SolutionDir)$(Platform)\$(Configuration)\; + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + CompileAsC + + + Console + true + %(AdditionalDependencies) + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + CompileAsC + + + Console + true + true + true + %(AdditionalDependencies) + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + CompileAsC + + + Console + true + %(AdditionalDependencies) + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + CompileAsC + + + Console + true + true + true + %(AdditionalDependencies) + + + + + + + + + \ No newline at end of file diff --git a/leechgrpc_test_client/leechgrpc_test_client.vcxproj.filters b/leechgrpc_test_client/leechgrpc_test_client.vcxproj.filters new file mode 100644 index 0000000..97d79b6 --- /dev/null +++ b/leechgrpc_test_client/leechgrpc_test_client.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/leechgrpc_test_client/leechgrpc_test_client.vcxproj.user b/leechgrpc_test_client/leechgrpc_test_client.vcxproj.user new file mode 100644 index 0000000..779e244 --- /dev/null +++ b/leechgrpc_test_client/leechgrpc_test_client.vcxproj.user @@ -0,0 +1,19 @@ + + + + $(TargetDir) + WindowsLocalDebugger + + + $(TargetDir) + WindowsLocalDebugger + + + $(TargetDir) + WindowsLocalDebugger + + + $(TargetDir) + WindowsLocalDebugger + + \ No newline at end of file diff --git a/leechgrpc_test_server/leechgrpc_test_server.cc b/leechgrpc_test_server/leechgrpc_test_server.cc new file mode 100644 index 0000000..a182e67 --- /dev/null +++ b/leechgrpc_test_server/leechgrpc_test_server.cc @@ -0,0 +1,63 @@ +#include +#include +#include "../libleechgrpc/leechgrpc.h" + +#pragma comment(lib, "libleechgrpc.lib") + +VOID TestServerCB(_In_ PVOID ctx, _In_ PBYTE pbIn, _In_ SIZE_T cbIn, _Out_ PBYTE *ppbOut, _Out_ SIZE_T *pcbOut) +{ + printf("[Server] Received message: %s\n", pbIn); + *pcbOut = strlen("MESSAGE FROM TEST SERVER!") + 1; + *ppbOut = (PBYTE)LocalAlloc(LMEM_FIXED, *pcbOut); + memcpy(*ppbOut, "MESSAGE FROM TEST SERVER!", *pcbOut); +} + +int main_insecure() +{ + + DWORD dwPORT = 28474; + HANDLE hGRPC; + + hGRPC = leechgrpc_server_create_insecure("0.0.0.0", dwPORT, NULL, TestServerCB); + if(!hGRPC) { + printf("[Server] Error creating gRPC server.\n"); + return 1; + } + + printf("[Server] server created!\n"); + + printf("[Server] start wait.\n"); + leechgrpc_server_wait(hGRPC); + + printf("[Server] wait completed - shutting down!\n"); + leechgrpc_server_shutdown(hGRPC); + return 0; +} + +int main_secure_tls() { + + DWORD dwPORT = 28474; + HANDLE hGRPC; + + hGRPC = leechgrpc_server_create_secure_p12("0.0.0.0", dwPORT, NULL, TestServerCB, "..\\..\\cert\\client-tls.cer", "..\\..\\cert\\server-tls.p12", "test"); + if(!hGRPC) { + printf("[Server] Error creating gRPC server.\n"); + return 1; + } + + printf("[Server] server created!\n"); + + printf("[Server] start wait.\n"); + leechgrpc_server_wait(hGRPC); + + printf("[Server] wait completed - shutting down!\n"); + leechgrpc_server_shutdown(hGRPC); + return 0; +} + + + +int main() +{ + main_secure_tls(); +} diff --git a/leechgrpc_test_server/leechgrpc_test_server.vcxproj b/leechgrpc_test_server/leechgrpc_test_server.vcxproj new file mode 100644 index 0000000..d2b815e --- /dev/null +++ b/leechgrpc_test_server/leechgrpc_test_server.vcxproj @@ -0,0 +1,147 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {2aa97c80-3f98-43df-a640-7d20bc575b4c} + leechgrpctestserver + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Platform)\$(Configuration)\; + + + $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Platform)\$(Configuration)\; + + + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(SolutionDir)$(Platform)\$(Configuration)\; + + + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(SolutionDir)$(Platform)\$(Configuration)\; + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/leechgrpc_test_server/leechgrpc_test_server.vcxproj.filters b/leechgrpc_test_server/leechgrpc_test_server.vcxproj.filters new file mode 100644 index 0000000..0b3779b --- /dev/null +++ b/leechgrpc_test_server/leechgrpc_test_server.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/leechgrpc_test_server/leechgrpc_test_server.vcxproj.user b/leechgrpc_test_server/leechgrpc_test_server.vcxproj.user new file mode 100644 index 0000000..69e22a0 --- /dev/null +++ b/leechgrpc_test_server/leechgrpc_test_server.vcxproj.user @@ -0,0 +1,19 @@ + + + + $(TargetDir) + WindowsLocalDebugger + + + $(TargetDir) + WindowsLocalDebugger + + + $(TargetDir) + WindowsLocalDebugger + + + $(TargetDir) + WindowsLocalDebugger + + \ No newline at end of file diff --git a/libleechgrpc.sln b/libleechgrpc.sln new file mode 100644 index 0000000..7749d07 --- /dev/null +++ b/libleechgrpc.sln @@ -0,0 +1,65 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35707.178 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libleechgrpc", "libleechgrpc\libleechgrpc.vcxproj", "{7F9DE005-851F-4817-8749-0396DA30B3F8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libleechgrpc_test_client", "leechgrpc_test_client\leechgrpc_test_client.vcxproj", "{6126530E-8882-4AAF-97E0-177C0DDB7EDE}" + ProjectSection(ProjectDependencies) = postProject + {7F9DE005-851F-4817-8749-0396DA30B3F8} = {7F9DE005-851F-4817-8749-0396DA30B3F8} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "leechgrpc_test_server", "leechgrpc_test_server\leechgrpc_test_server.vcxproj", "{2AA97C80-3F98-43DF-A640-7D20BC575B4C}" + ProjectSection(ProjectDependencies) = postProject + {7F9DE005-851F-4817-8749-0396DA30B3F8} = {7F9DE005-851F-4817-8749-0396DA30B3F8} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cert", "cert", "{8B55BAB8-A859-4E01-961F-4C7CF896F07C}" + ProjectSection(SolutionItems) = preProject + cert\client-tls.key = cert\client-tls.key + cert\client-tls.cer = cert\client-tls.cer + cert\client-tls.p12 = cert\client-tls.p12 + cert\password.txt = cert\password.txt + cert\server-tls.key = cert\server-tls.key + cert\server-tls.cer = cert\server-tls.cer + cert\server-tls.p12 = cert\server-tls.p12 + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7F9DE005-851F-4817-8749-0396DA30B3F8}.Debug|x64.ActiveCfg = Debug|x64 + {7F9DE005-851F-4817-8749-0396DA30B3F8}.Debug|x64.Build.0 = Debug|x64 + {7F9DE005-851F-4817-8749-0396DA30B3F8}.Debug|x86.ActiveCfg = Debug|Win32 + {7F9DE005-851F-4817-8749-0396DA30B3F8}.Debug|x86.Build.0 = Debug|Win32 + {7F9DE005-851F-4817-8749-0396DA30B3F8}.Release|x64.ActiveCfg = Release|x64 + {7F9DE005-851F-4817-8749-0396DA30B3F8}.Release|x64.Build.0 = Release|x64 + {7F9DE005-851F-4817-8749-0396DA30B3F8}.Release|x86.ActiveCfg = Release|Win32 + {7F9DE005-851F-4817-8749-0396DA30B3F8}.Release|x86.Build.0 = Release|Win32 + {6126530E-8882-4AAF-97E0-177C0DDB7EDE}.Debug|x64.ActiveCfg = Debug|x64 + {6126530E-8882-4AAF-97E0-177C0DDB7EDE}.Debug|x64.Build.0 = Debug|x64 + {6126530E-8882-4AAF-97E0-177C0DDB7EDE}.Debug|x86.ActiveCfg = Debug|Win32 + {6126530E-8882-4AAF-97E0-177C0DDB7EDE}.Debug|x86.Build.0 = Debug|Win32 + {6126530E-8882-4AAF-97E0-177C0DDB7EDE}.Release|x64.ActiveCfg = Release|x64 + {6126530E-8882-4AAF-97E0-177C0DDB7EDE}.Release|x64.Build.0 = Release|x64 + {6126530E-8882-4AAF-97E0-177C0DDB7EDE}.Release|x86.ActiveCfg = Release|Win32 + {6126530E-8882-4AAF-97E0-177C0DDB7EDE}.Release|x86.Build.0 = Release|Win32 + {2AA97C80-3F98-43DF-A640-7D20BC575B4C}.Debug|x64.ActiveCfg = Debug|x64 + {2AA97C80-3F98-43DF-A640-7D20BC575B4C}.Debug|x64.Build.0 = Debug|x64 + {2AA97C80-3F98-43DF-A640-7D20BC575B4C}.Debug|x86.ActiveCfg = Debug|Win32 + {2AA97C80-3F98-43DF-A640-7D20BC575B4C}.Debug|x86.Build.0 = Debug|Win32 + {2AA97C80-3F98-43DF-A640-7D20BC575B4C}.Release|x64.ActiveCfg = Release|x64 + {2AA97C80-3F98-43DF-A640-7D20BC575B4C}.Release|x64.Build.0 = Release|x64 + {2AA97C80-3F98-43DF-A640-7D20BC575B4C}.Release|x86.ActiveCfg = Release|Win32 + {2AA97C80-3F98-43DF-A640-7D20BC575B4C}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libleechgrpc/CMakeLists.txt b/libleechgrpc/CMakeLists.txt new file mode 100644 index 0000000..b323a3e --- /dev/null +++ b/libleechgrpc/CMakeLists.txt @@ -0,0 +1,83 @@ +# Copyright 2018 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# cmake build file for C++ helloworld example. +# Assumes protobuf and gRPC have been installed using cmake. +# See cmake_externalproject/CMakeLists.txt for all-in-one cmake build +# that automatically builds all the dependencies before building helloworld. + +cmake_minimum_required(VERSION 3.8) + +project(leechgrpc C CXX) + +include(./common.cmake) + +#set(OPENSSL_USE_STATIC_LIBS TRUE) +#find_package(OpenSSL REQUIRED) + +# Proto file +get_filename_component(hw_proto "./proto/leechgrpc.proto" ABSOLUTE) +get_filename_component(hw_proto_path "${hw_proto}" PATH) + +# Generated sources +set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/leechgrpc.pb.cc") +set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/leechgrpc.pb.h") +set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/leechgrpc.grpc.pb.cc") +set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/leechgrpc.grpc.pb.h") +add_custom_command( + OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}" + COMMAND ${_PROTOBUF_PROTOC} + ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" + --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" + -I "${hw_proto_path}" + --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" + "${hw_proto}" + DEPENDS "${hw_proto}") + +# Include generated *.pb.h files +include_directories("${CMAKE_CURRENT_BINARY_DIR}") + +# hw_grpc_proto +add_library(hw_grpc_proto + ${hw_grpc_srcs} + ${hw_grpc_hdrs} + ${hw_proto_srcs} + ${hw_proto_hdrs}) +target_link_libraries(hw_grpc_proto + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) + +# --- [ Final shared library ] ----------------------------------------------- +# We now create a shared library that pulls in everything statically +# (except for system libs). On Linux, you need position-independent code +# for all objects, which we enabled earlier with CMAKE_POSITION_INDEPENDENT_CODE=TRUE +# when building gRPC and with the default setting for these libraries here. + +add_library(leechgrpc SHARED "${CMAKE_CURRENT_SOURCE_DIR}/leechgrpc_client.cc" "${CMAKE_CURRENT_SOURCE_DIR}/leechgrpc_server.cc" "${CMAKE_CURRENT_SOURCE_DIR}/oscompatibility.cc" "${CMAKE_CURRENT_SOURCE_DIR}/util.cc") +# Link the static pieces +target_link_libraries(leechgrpc + PRIVATE + hw_grpc_proto + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF} +# OpenSSL::SSL +# OpenSSL::Crypto +) + +# Provide an soname for the library if desired: +set_target_properties(leechgrpc PROPERTIES + OUTPUT_NAME "leechgrpc" + SOVERSION "1" +) + diff --git a/libleechgrpc/common.cmake b/libleechgrpc/common.cmake new file mode 100644 index 0000000..df9bc4d --- /dev/null +++ b/libleechgrpc/common.cmake @@ -0,0 +1,122 @@ +# Copyright 2018 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# cmake build file for C++ route_guide example. +# Assumes protobuf and gRPC have been installed using cmake. +# See cmake_externalproject/CMakeLists.txt for all-in-one cmake build +# that automatically builds all the dependencies before building route_guide. + +cmake_minimum_required(VERSION 3.8) + +if(MSVC) + add_definitions(-D_WIN32_WINNT=0x600) +endif() + +find_package(Threads REQUIRED) + +if(GRPC_AS_SUBMODULE) + # One way to build a projects that uses gRPC is to just include the + # entire gRPC project tree via "add_subdirectory". + # This approach is very simple to use, but the are some potential + # disadvantages: + # * it includes gRPC's CMakeLists.txt directly into your build script + # without and that can make gRPC's internal setting interfere with your + # own build. + # * depending on what's installed on your system, the contents of submodules + # in gRPC's third_party/* might need to be available (and there might be + # additional prerequisites required to build them). Consider using + # the gRPC_*_PROVIDER options to fine-tune the expected behavior. + # + # A more robust approach to add dependency on gRPC is using + # cmake's ExternalProject_Add (see cmake_externalproject/CMakeLists.txt). + + # Include the gRPC's cmake build (normally grpc source code would live + # in a git submodule called "third_party/grpc", but this example lives in + # the same repository as gRPC sources, so we just look a few directories up) + add_subdirectory(../../.. ${CMAKE_CURRENT_BINARY_DIR}/grpc EXCLUDE_FROM_ALL) + message(STATUS "Using gRPC via add_subdirectory.") + + # After using add_subdirectory, we can now use the grpc targets directly from + # this build. + set(_PROTOBUF_LIBPROTOBUF libprotobuf) + set(_REFLECTION grpc++_reflection) + set(_ORCA_SERVICE grpcpp_orca_service) + if(CMAKE_CROSSCOMPILING) + find_program(_PROTOBUF_PROTOC protoc) + else() + set(_PROTOBUF_PROTOC $) + endif() + set(_GRPC_GRPCPP grpc++) + if(CMAKE_CROSSCOMPILING) + find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) + else() + set(_GRPC_CPP_PLUGIN_EXECUTABLE $) + endif() +elseif(GRPC_FETCHCONTENT) + # Another way is to use CMake's FetchContent module to clone gRPC at + # configure time. This makes gRPC's source code available to your project, + # similar to a git submodule. + message(STATUS "Using gRPC via add_subdirectory (FetchContent).") + include(FetchContent) + FetchContent_Declare( + grpc + GIT_REPOSITORY https://github.com/grpc/grpc.git + # when using gRPC, you will actually set this to an existing tag, such as + # v1.25.0, v1.26.0 etc.. + # For the purpose of testing, we override the tag used to the commit + # that's currently under test. + GIT_TAG vGRPC_TAG_VERSION_OF_YOUR_CHOICE) + FetchContent_MakeAvailable(grpc) + + # Since FetchContent uses add_subdirectory under the hood, we can use + # the grpc targets directly from this build. + set(_PROTOBUF_LIBPROTOBUF libprotobuf) + set(_REFLECTION grpc++_reflection) + set(_PROTOBUF_PROTOC $) + set(_GRPC_GRPCPP grpc++) + if(CMAKE_CROSSCOMPILING) + find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) + else() + set(_GRPC_CPP_PLUGIN_EXECUTABLE $) + endif() +else() + # This branch assumes that gRPC and all its dependencies are already installed + # on this system, so they can be located by find_package(). + + # Find Protobuf installation + # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. + option(protobuf_MODULE_COMPATIBLE TRUE) + find_package(Protobuf CONFIG REQUIRED) + message(STATUS "Using protobuf ${Protobuf_VERSION}") + + set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) + set(_REFLECTION gRPC::grpc++_reflection) + if(CMAKE_CROSSCOMPILING) + find_program(_PROTOBUF_PROTOC protoc) + else() + set(_PROTOBUF_PROTOC $) + endif() + + # Find gRPC installation + # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. + find_package(gRPC CONFIG REQUIRED) + message(STATUS "Using gRPC ${gRPC_VERSION}") + + set(_GRPC_GRPCPP gRPC::grpc++) + if(CMAKE_CROSSCOMPILING) + find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) + else() + set(_GRPC_CPP_PLUGIN_EXECUTABLE $) + endif() +endif() diff --git a/libleechgrpc/generated/leechgrpc.grpc.pb.cc b/libleechgrpc/generated/leechgrpc.grpc.pb.cc new file mode 100644 index 0000000..d4d1fd3 --- /dev/null +++ b/libleechgrpc/generated/leechgrpc.grpc.pb.cc @@ -0,0 +1,86 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: leechgrpc.proto + +#include "leechgrpc.pb.h" +#include "leechgrpc.grpc.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace leechrpc { + +static const char* LeechRpc_method_names[] = { + "/leechrpc.LeechRpc/ReservedSubmitCommand", +}; + +std::unique_ptr< LeechRpc::Stub> LeechRpc::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { + (void)options; + std::unique_ptr< LeechRpc::Stub> stub(new LeechRpc::Stub(channel, options)); + return stub; +} + +LeechRpc::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) + : channel_(channel), rpcmethod_ReservedSubmitCommand_(LeechRpc_method_names[0], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + {} + +::grpc::Status LeechRpc::Stub::ReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::leechrpc::SubmitCommandResponse* response) { + return ::grpc::internal::BlockingUnaryCall< ::leechrpc::SubmitCommandRequest, ::leechrpc::SubmitCommandResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_ReservedSubmitCommand_, context, request, response); +} + +void LeechRpc::Stub::async::ReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest* request, ::leechrpc::SubmitCommandResponse* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::leechrpc::SubmitCommandRequest, ::leechrpc::SubmitCommandResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_ReservedSubmitCommand_, context, request, response, std::move(f)); +} + +void LeechRpc::Stub::async::ReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest* request, ::leechrpc::SubmitCommandResponse* response, ::grpc::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_ReservedSubmitCommand_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::leechrpc::SubmitCommandResponse>* LeechRpc::Stub::PrepareAsyncReservedSubmitCommandRaw(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::leechrpc::SubmitCommandResponse, ::leechrpc::SubmitCommandRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_ReservedSubmitCommand_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::leechrpc::SubmitCommandResponse>* LeechRpc::Stub::AsyncReservedSubmitCommandRaw(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncReservedSubmitCommandRaw(context, request, cq); + result->StartCall(); + return result; +} + +LeechRpc::Service::Service() { + AddMethod(new ::grpc::internal::RpcServiceMethod( + LeechRpc_method_names[0], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< LeechRpc::Service, ::leechrpc::SubmitCommandRequest, ::leechrpc::SubmitCommandResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](LeechRpc::Service* service, + ::grpc::ServerContext* ctx, + const ::leechrpc::SubmitCommandRequest* req, + ::leechrpc::SubmitCommandResponse* resp) { + return service->ReservedSubmitCommand(ctx, req, resp); + }, this))); +} + +LeechRpc::Service::~Service() { +} + +::grpc::Status LeechRpc::Service::ReservedSubmitCommand(::grpc::ServerContext* context, const ::leechrpc::SubmitCommandRequest* request, ::leechrpc::SubmitCommandResponse* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + + +} // namespace leechrpc + diff --git a/libleechgrpc/generated/leechgrpc.grpc.pb.h b/libleechgrpc/generated/leechgrpc.grpc.pb.h new file mode 100644 index 0000000..c7a3911 --- /dev/null +++ b/libleechgrpc/generated/leechgrpc.grpc.pb.h @@ -0,0 +1,243 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: leechgrpc.proto +#ifndef GRPC_leechgrpc_2eproto__INCLUDED +#define GRPC_leechgrpc_2eproto__INCLUDED + +#include "leechgrpc.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace leechrpc { + +class LeechRpc final { + public: + static constexpr char const* service_full_name() { + return "leechrpc.LeechRpc"; + } + class StubInterface { + public: + virtual ~StubInterface() {} + // Mirrors the MSRPC call: LeechRpc_ReservedSubmitCommand + virtual ::grpc::Status ReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::leechrpc::SubmitCommandResponse* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::leechrpc::SubmitCommandResponse>> AsyncReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::leechrpc::SubmitCommandResponse>>(AsyncReservedSubmitCommandRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::leechrpc::SubmitCommandResponse>> PrepareAsyncReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::leechrpc::SubmitCommandResponse>>(PrepareAsyncReservedSubmitCommandRaw(context, request, cq)); + } + class async_interface { + public: + virtual ~async_interface() {} + // Mirrors the MSRPC call: LeechRpc_ReservedSubmitCommand + virtual void ReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest* request, ::leechrpc::SubmitCommandResponse* response, std::function) = 0; + virtual void ReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest* request, ::leechrpc::SubmitCommandResponse* response, ::grpc::ClientUnaryReactor* reactor) = 0; + }; + typedef class async_interface experimental_async_interface; + virtual class async_interface* async() { return nullptr; } + class async_interface* experimental_async() { return async(); } + private: + virtual ::grpc::ClientAsyncResponseReaderInterface< ::leechrpc::SubmitCommandResponse>* AsyncReservedSubmitCommandRaw(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::leechrpc::SubmitCommandResponse>* PrepareAsyncReservedSubmitCommandRaw(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::grpc::CompletionQueue* cq) = 0; + }; + class Stub final : public StubInterface { + public: + Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); + ::grpc::Status ReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::leechrpc::SubmitCommandResponse* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::leechrpc::SubmitCommandResponse>> AsyncReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::leechrpc::SubmitCommandResponse>>(AsyncReservedSubmitCommandRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::leechrpc::SubmitCommandResponse>> PrepareAsyncReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::leechrpc::SubmitCommandResponse>>(PrepareAsyncReservedSubmitCommandRaw(context, request, cq)); + } + class async final : + public StubInterface::async_interface { + public: + void ReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest* request, ::leechrpc::SubmitCommandResponse* response, std::function) override; + void ReservedSubmitCommand(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest* request, ::leechrpc::SubmitCommandResponse* response, ::grpc::ClientUnaryReactor* reactor) override; + private: + friend class Stub; + explicit async(Stub* stub): stub_(stub) { } + Stub* stub() { return stub_; } + Stub* stub_; + }; + class async* async() override { return &async_stub_; } + + private: + std::shared_ptr< ::grpc::ChannelInterface> channel_; + class async async_stub_{this}; + ::grpc::ClientAsyncResponseReader< ::leechrpc::SubmitCommandResponse>* AsyncReservedSubmitCommandRaw(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::leechrpc::SubmitCommandResponse>* PrepareAsyncReservedSubmitCommandRaw(::grpc::ClientContext* context, const ::leechrpc::SubmitCommandRequest& request, ::grpc::CompletionQueue* cq) override; + const ::grpc::internal::RpcMethod rpcmethod_ReservedSubmitCommand_; + }; + static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); + + class Service : public ::grpc::Service { + public: + Service(); + virtual ~Service(); + // Mirrors the MSRPC call: LeechRpc_ReservedSubmitCommand + virtual ::grpc::Status ReservedSubmitCommand(::grpc::ServerContext* context, const ::leechrpc::SubmitCommandRequest* request, ::leechrpc::SubmitCommandResponse* response); + }; + template + class WithAsyncMethod_ReservedSubmitCommand : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_ReservedSubmitCommand() { + ::grpc::Service::MarkMethodAsync(0); + } + ~WithAsyncMethod_ReservedSubmitCommand() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status ReservedSubmitCommand(::grpc::ServerContext* /*context*/, const ::leechrpc::SubmitCommandRequest* /*request*/, ::leechrpc::SubmitCommandResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestReservedSubmitCommand(::grpc::ServerContext* context, ::leechrpc::SubmitCommandRequest* request, ::grpc::ServerAsyncResponseWriter< ::leechrpc::SubmitCommandResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + typedef WithAsyncMethod_ReservedSubmitCommand AsyncService; + template + class WithCallbackMethod_ReservedSubmitCommand : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithCallbackMethod_ReservedSubmitCommand() { + ::grpc::Service::MarkMethodCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::leechrpc::SubmitCommandRequest, ::leechrpc::SubmitCommandResponse>( + [this]( + ::grpc::CallbackServerContext* context, const ::leechrpc::SubmitCommandRequest* request, ::leechrpc::SubmitCommandResponse* response) { return this->ReservedSubmitCommand(context, request, response); }));} + void SetMessageAllocatorFor_ReservedSubmitCommand( + ::grpc::MessageAllocator< ::leechrpc::SubmitCommandRequest, ::leechrpc::SubmitCommandResponse>* allocator) { + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(0); + static_cast<::grpc::internal::CallbackUnaryHandler< ::leechrpc::SubmitCommandRequest, ::leechrpc::SubmitCommandResponse>*>(handler) + ->SetMessageAllocator(allocator); + } + ~WithCallbackMethod_ReservedSubmitCommand() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status ReservedSubmitCommand(::grpc::ServerContext* /*context*/, const ::leechrpc::SubmitCommandRequest* /*request*/, ::leechrpc::SubmitCommandResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* ReservedSubmitCommand( + ::grpc::CallbackServerContext* /*context*/, const ::leechrpc::SubmitCommandRequest* /*request*/, ::leechrpc::SubmitCommandResponse* /*response*/) { return nullptr; } + }; + typedef WithCallbackMethod_ReservedSubmitCommand CallbackService; + typedef CallbackService ExperimentalCallbackService; + template + class WithGenericMethod_ReservedSubmitCommand : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_ReservedSubmitCommand() { + ::grpc::Service::MarkMethodGeneric(0); + } + ~WithGenericMethod_ReservedSubmitCommand() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status ReservedSubmitCommand(::grpc::ServerContext* /*context*/, const ::leechrpc::SubmitCommandRequest* /*request*/, ::leechrpc::SubmitCommandResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithRawMethod_ReservedSubmitCommand : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_ReservedSubmitCommand() { + ::grpc::Service::MarkMethodRaw(0); + } + ~WithRawMethod_ReservedSubmitCommand() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status ReservedSubmitCommand(::grpc::ServerContext* /*context*/, const ::leechrpc::SubmitCommandRequest* /*request*/, ::leechrpc::SubmitCommandResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestReservedSubmitCommand(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawCallbackMethod_ReservedSubmitCommand : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawCallbackMethod_ReservedSubmitCommand() { + ::grpc::Service::MarkMethodRawCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ReservedSubmitCommand(context, request, response); })); + } + ~WithRawCallbackMethod_ReservedSubmitCommand() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status ReservedSubmitCommand(::grpc::ServerContext* /*context*/, const ::leechrpc::SubmitCommandRequest* /*request*/, ::leechrpc::SubmitCommandResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* ReservedSubmitCommand( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) { return nullptr; } + }; + template + class WithStreamedUnaryMethod_ReservedSubmitCommand : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_ReservedSubmitCommand() { + ::grpc::Service::MarkMethodStreamed(0, + new ::grpc::internal::StreamedUnaryHandler< + ::leechrpc::SubmitCommandRequest, ::leechrpc::SubmitCommandResponse>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::leechrpc::SubmitCommandRequest, ::leechrpc::SubmitCommandResponse>* streamer) { + return this->StreamedReservedSubmitCommand(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_ReservedSubmitCommand() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status ReservedSubmitCommand(::grpc::ServerContext* /*context*/, const ::leechrpc::SubmitCommandRequest* /*request*/, ::leechrpc::SubmitCommandResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedReservedSubmitCommand(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::leechrpc::SubmitCommandRequest,::leechrpc::SubmitCommandResponse>* server_unary_streamer) = 0; + }; + typedef WithStreamedUnaryMethod_ReservedSubmitCommand StreamedUnaryService; + typedef Service SplitStreamedService; + typedef WithStreamedUnaryMethod_ReservedSubmitCommand StreamedService; +}; + +} // namespace leechrpc + + +#endif // GRPC_leechgrpc_2eproto__INCLUDED diff --git a/libleechgrpc/generated/leechgrpc.pb.cc b/libleechgrpc/generated/leechgrpc.pb.cc new file mode 100644 index 0000000..1cb5aca --- /dev/null +++ b/libleechgrpc/generated/leechgrpc.pb.cc @@ -0,0 +1,609 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: leechgrpc.proto +// Protobuf C++ Version: 5.29.2 + +#include "leechgrpc.pb.h" + +#include +#include +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/generated_message_tctable_impl.h" +#include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/wire_format_lite.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/reflection_ops.h" +#include "google/protobuf/wire_format.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" +PROTOBUF_PRAGMA_INIT_SEG +namespace _pb = ::google::protobuf; +namespace _pbi = ::google::protobuf::internal; +namespace _fl = ::google::protobuf::internal::field_layout; +namespace leechrpc { + +inline constexpr SubmitCommandResponse::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : pbout_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR SubmitCommandResponse::SubmitCommandResponse(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct SubmitCommandResponseDefaultTypeInternal { + PROTOBUF_CONSTEXPR SubmitCommandResponseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~SubmitCommandResponseDefaultTypeInternal() {} + union { + SubmitCommandResponse _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SubmitCommandResponseDefaultTypeInternal _SubmitCommandResponse_default_instance_; + +inline constexpr SubmitCommandRequest::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : pbin_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR SubmitCommandRequest::SubmitCommandRequest(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct SubmitCommandRequestDefaultTypeInternal { + PROTOBUF_CONSTEXPR SubmitCommandRequestDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~SubmitCommandRequestDefaultTypeInternal() {} + union { + SubmitCommandRequest _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SubmitCommandRequestDefaultTypeInternal _SubmitCommandRequest_default_instance_; +} // namespace leechrpc +static constexpr const ::_pb::EnumDescriptor** + file_level_enum_descriptors_leechgrpc_2eproto = nullptr; +static constexpr const ::_pb::ServiceDescriptor** + file_level_service_descriptors_leechgrpc_2eproto = nullptr; +const ::uint32_t + TableStruct_leechgrpc_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::leechrpc::SubmitCommandRequest, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::leechrpc::SubmitCommandRequest, _impl_.pbin_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::leechrpc::SubmitCommandResponse, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::leechrpc::SubmitCommandResponse, _impl_.pbout_), +}; + +static const ::_pbi::MigrationSchema + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + {0, -1, -1, sizeof(::leechrpc::SubmitCommandRequest)}, + {9, -1, -1, sizeof(::leechrpc::SubmitCommandResponse)}, +}; +static const ::_pb::Message* const file_default_instances[] = { + &::leechrpc::_SubmitCommandRequest_default_instance_._instance, + &::leechrpc::_SubmitCommandResponse_default_instance_._instance, +}; +const char descriptor_table_protodef_leechgrpc_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + "\n\017leechgrpc.proto\022\010leechrpc\"$\n\024SubmitCom" + "mandRequest\022\014\n\004pbIn\030\001 \001(\014\"&\n\025SubmitComma" + "ndResponse\022\r\n\005pbOut\030\001 \001(\0142d\n\010LeechRpc\022X\n" + "\025ReservedSubmitCommand\022\036.leechrpc.Submit" + "CommandRequest\032\037.leechrpc.SubmitCommandR" + "esponseb\006proto3" +}; +static ::absl::once_flag descriptor_table_leechgrpc_2eproto_once; +PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_leechgrpc_2eproto = { + false, + false, + 215, + descriptor_table_protodef_leechgrpc_2eproto, + "leechgrpc.proto", + &descriptor_table_leechgrpc_2eproto_once, + nullptr, + 0, + 2, + schemas, + file_default_instances, + TableStruct_leechgrpc_2eproto::offsets, + file_level_enum_descriptors_leechgrpc_2eproto, + file_level_service_descriptors_leechgrpc_2eproto, +}; +namespace leechrpc { +// =================================================================== + +class SubmitCommandRequest::_Internal { + public: +}; + +SubmitCommandRequest::SubmitCommandRequest(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, _class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:leechrpc.SubmitCommandRequest) +} +inline PROTOBUF_NDEBUG_INLINE SubmitCommandRequest::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from, const ::leechrpc::SubmitCommandRequest& from_msg) + : pbin_(arena, from.pbin_), + _cached_size_{0} {} + +SubmitCommandRequest::SubmitCommandRequest( + ::google::protobuf::Arena* arena, + const SubmitCommandRequest& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, _class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SubmitCommandRequest* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + + // @@protoc_insertion_point(copy_constructor:leechrpc.SubmitCommandRequest) +} +inline PROTOBUF_NDEBUG_INLINE SubmitCommandRequest::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : pbin_(arena), + _cached_size_{0} {} + +inline void SubmitCommandRequest::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +SubmitCommandRequest::~SubmitCommandRequest() { + // @@protoc_insertion_point(destructor:leechrpc.SubmitCommandRequest) + SharedDtor(*this); +} +inline void SubmitCommandRequest::SharedDtor(MessageLite& self) { + SubmitCommandRequest& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.pbin_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* SubmitCommandRequest::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) SubmitCommandRequest(arena); +} +constexpr auto SubmitCommandRequest::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(SubmitCommandRequest), + alignof(SubmitCommandRequest)); +} +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::google::protobuf::internal::ClassDataFull SubmitCommandRequest::_class_data_ = { + ::google::protobuf::internal::ClassData{ + &_SubmitCommandRequest_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &SubmitCommandRequest::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &SubmitCommandRequest::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &SubmitCommandRequest::ByteSizeLong, + &SubmitCommandRequest::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(SubmitCommandRequest, _impl_._cached_size_), + false, + }, + &SubmitCommandRequest::kDescriptorMethods, + &descriptor_table_leechgrpc_2eproto, + nullptr, // tracker +}; +const ::google::protobuf::internal::ClassData* SubmitCommandRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(_class_data_.tc_table); + return _class_data_.base(); +} +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> SubmitCommandRequest::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + _class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::leechrpc::SubmitCommandRequest>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // bytes pbIn = 1; + {::_pbi::TcParser::FastBS1, + {10, 63, 0, PROTOBUF_FIELD_OFFSET(SubmitCommandRequest, _impl_.pbin_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // bytes pbIn = 1; + {PROTOBUF_FIELD_OFFSET(SubmitCommandRequest, _impl_.pbin_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kBytes | ::_fl::kRepAString)}, + }}, + // no aux_entries + {{ + }}, +}; + +PROTOBUF_NOINLINE void SubmitCommandRequest::Clear() { +// @@protoc_insertion_point(message_clear_start:leechrpc.SubmitCommandRequest) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.pbin_.ClearToEmpty(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* SubmitCommandRequest::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const SubmitCommandRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* SubmitCommandRequest::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const SubmitCommandRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:leechrpc.SubmitCommandRequest) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // bytes pbIn = 1; + if (!this_._internal_pbin().empty()) { + const std::string& _s = this_._internal_pbin(); + target = stream->WriteBytesMaybeAliased(1, _s, target); + } + + if (PROTOBUF_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:leechrpc.SubmitCommandRequest) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t SubmitCommandRequest::ByteSizeLong(const MessageLite& base) { + const SubmitCommandRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t SubmitCommandRequest::ByteSizeLong() const { + const SubmitCommandRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:leechrpc.SubmitCommandRequest) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + { + // bytes pbIn = 1; + if (!this_._internal_pbin().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::BytesSize( + this_._internal_pbin()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } + +void SubmitCommandRequest::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:leechrpc.SubmitCommandRequest) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_pbin().empty()) { + _this->_internal_set_pbin(from._internal_pbin()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void SubmitCommandRequest::CopyFrom(const SubmitCommandRequest& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:leechrpc.SubmitCommandRequest) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void SubmitCommandRequest::InternalSwap(SubmitCommandRequest* PROTOBUF_RESTRICT other) { + using std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.pbin_, &other->_impl_.pbin_, arena); +} + +::google::protobuf::Metadata SubmitCommandRequest::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class SubmitCommandResponse::_Internal { + public: +}; + +SubmitCommandResponse::SubmitCommandResponse(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, _class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:leechrpc.SubmitCommandResponse) +} +inline PROTOBUF_NDEBUG_INLINE SubmitCommandResponse::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from, const ::leechrpc::SubmitCommandResponse& from_msg) + : pbout_(arena, from.pbout_), + _cached_size_{0} {} + +SubmitCommandResponse::SubmitCommandResponse( + ::google::protobuf::Arena* arena, + const SubmitCommandResponse& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, _class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SubmitCommandResponse* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + + // @@protoc_insertion_point(copy_constructor:leechrpc.SubmitCommandResponse) +} +inline PROTOBUF_NDEBUG_INLINE SubmitCommandResponse::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : pbout_(arena), + _cached_size_{0} {} + +inline void SubmitCommandResponse::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +SubmitCommandResponse::~SubmitCommandResponse() { + // @@protoc_insertion_point(destructor:leechrpc.SubmitCommandResponse) + SharedDtor(*this); +} +inline void SubmitCommandResponse::SharedDtor(MessageLite& self) { + SubmitCommandResponse& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.pbout_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* SubmitCommandResponse::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) SubmitCommandResponse(arena); +} +constexpr auto SubmitCommandResponse::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(SubmitCommandResponse), + alignof(SubmitCommandResponse)); +} +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::google::protobuf::internal::ClassDataFull SubmitCommandResponse::_class_data_ = { + ::google::protobuf::internal::ClassData{ + &_SubmitCommandResponse_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &SubmitCommandResponse::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &SubmitCommandResponse::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &SubmitCommandResponse::ByteSizeLong, + &SubmitCommandResponse::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(SubmitCommandResponse, _impl_._cached_size_), + false, + }, + &SubmitCommandResponse::kDescriptorMethods, + &descriptor_table_leechgrpc_2eproto, + nullptr, // tracker +}; +const ::google::protobuf::internal::ClassData* SubmitCommandResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(_class_data_.tc_table); + return _class_data_.base(); +} +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> SubmitCommandResponse::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + _class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::leechrpc::SubmitCommandResponse>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // bytes pbOut = 1; + {::_pbi::TcParser::FastBS1, + {10, 63, 0, PROTOBUF_FIELD_OFFSET(SubmitCommandResponse, _impl_.pbout_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // bytes pbOut = 1; + {PROTOBUF_FIELD_OFFSET(SubmitCommandResponse, _impl_.pbout_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kBytes | ::_fl::kRepAString)}, + }}, + // no aux_entries + {{ + }}, +}; + +PROTOBUF_NOINLINE void SubmitCommandResponse::Clear() { +// @@protoc_insertion_point(message_clear_start:leechrpc.SubmitCommandResponse) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.pbout_.ClearToEmpty(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* SubmitCommandResponse::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const SubmitCommandResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* SubmitCommandResponse::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const SubmitCommandResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:leechrpc.SubmitCommandResponse) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // bytes pbOut = 1; + if (!this_._internal_pbout().empty()) { + const std::string& _s = this_._internal_pbout(); + target = stream->WriteBytesMaybeAliased(1, _s, target); + } + + if (PROTOBUF_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:leechrpc.SubmitCommandResponse) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t SubmitCommandResponse::ByteSizeLong(const MessageLite& base) { + const SubmitCommandResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t SubmitCommandResponse::ByteSizeLong() const { + const SubmitCommandResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:leechrpc.SubmitCommandResponse) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + { + // bytes pbOut = 1; + if (!this_._internal_pbout().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::BytesSize( + this_._internal_pbout()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } + +void SubmitCommandResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:leechrpc.SubmitCommandResponse) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_pbout().empty()) { + _this->_internal_set_pbout(from._internal_pbout()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void SubmitCommandResponse::CopyFrom(const SubmitCommandResponse& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:leechrpc.SubmitCommandResponse) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void SubmitCommandResponse::InternalSwap(SubmitCommandResponse* PROTOBUF_RESTRICT other) { + using std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.pbout_, &other->_impl_.pbout_, arena); +} + +::google::protobuf::Metadata SubmitCommandResponse::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// @@protoc_insertion_point(namespace_scope) +} // namespace leechrpc +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google +// @@protoc_insertion_point(global_scope) +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_leechgrpc_2eproto), + ::std::false_type{}); +#include "google/protobuf/port_undef.inc" diff --git a/libleechgrpc/generated/leechgrpc.pb.h b/libleechgrpc/generated/leechgrpc.pb.h new file mode 100644 index 0000000..9ff7870 --- /dev/null +++ b/libleechgrpc/generated/leechgrpc.pb.h @@ -0,0 +1,593 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: leechgrpc.proto +// Protobuf C++ Version: 5.29.2 + +#ifndef leechgrpc_2eproto_2epb_2eh +#define leechgrpc_2eproto_2epb_2eh + +#include +#include +#include +#include + +#include "google/protobuf/runtime_version.h" +#if PROTOBUF_VERSION != 5029002 +#error "Protobuf C++ gencode is built with an incompatible version of" +#error "Protobuf C++ headers/runtime. See" +#error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" +#endif +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/generated_message_tctable_decl.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/metadata_lite.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/repeated_field.h" // IWYU pragma: export +#include "google/protobuf/extension_set.h" // IWYU pragma: export +#include "google/protobuf/unknown_field_set.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" + +#define PROTOBUF_INTERNAL_EXPORT_leechgrpc_2eproto + +namespace google { +namespace protobuf { +namespace internal { +template +::absl::string_view GetAnyMessageName(); +} // namespace internal +} // namespace protobuf +} // namespace google + +// Internal implementation detail -- do not use these members. +struct TableStruct_leechgrpc_2eproto { + static const ::uint32_t offsets[]; +}; +extern const ::google::protobuf::internal::DescriptorTable + descriptor_table_leechgrpc_2eproto; +namespace leechrpc { +class SubmitCommandRequest; +struct SubmitCommandRequestDefaultTypeInternal; +extern SubmitCommandRequestDefaultTypeInternal _SubmitCommandRequest_default_instance_; +class SubmitCommandResponse; +struct SubmitCommandResponseDefaultTypeInternal; +extern SubmitCommandResponseDefaultTypeInternal _SubmitCommandResponse_default_instance_; +} // namespace leechrpc +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google + +namespace leechrpc { + +// =================================================================== + + +// ------------------------------------------------------------------- + +class SubmitCommandResponse final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:leechrpc.SubmitCommandResponse) */ { + public: + inline SubmitCommandResponse() : SubmitCommandResponse(nullptr) {} + ~SubmitCommandResponse() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(SubmitCommandResponse* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(SubmitCommandResponse)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR SubmitCommandResponse( + ::google::protobuf::internal::ConstantInitialized); + + inline SubmitCommandResponse(const SubmitCommandResponse& from) : SubmitCommandResponse(nullptr, from) {} + inline SubmitCommandResponse(SubmitCommandResponse&& from) noexcept + : SubmitCommandResponse(nullptr, std::move(from)) {} + inline SubmitCommandResponse& operator=(const SubmitCommandResponse& from) { + CopyFrom(from); + return *this; + } + inline SubmitCommandResponse& operator=(SubmitCommandResponse&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const SubmitCommandResponse& default_instance() { + return *internal_default_instance(); + } + static inline const SubmitCommandResponse* internal_default_instance() { + return reinterpret_cast( + &_SubmitCommandResponse_default_instance_); + } + static constexpr int kIndexInFileMessages = 1; + friend void swap(SubmitCommandResponse& a, SubmitCommandResponse& b) { a.Swap(&b); } + inline void Swap(SubmitCommandResponse* other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SubmitCommandResponse* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + SubmitCommandResponse* New(::google::protobuf::Arena* arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const SubmitCommandResponse& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const SubmitCommandResponse& from) { SubmitCommandResponse::MergeImpl(*this, from); } + + private: + static void MergeImpl( + ::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(SubmitCommandResponse* other); + private: + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "leechrpc.SubmitCommandResponse"; } + + protected: + explicit SubmitCommandResponse(::google::protobuf::Arena* arena); + SubmitCommandResponse(::google::protobuf::Arena* arena, const SubmitCommandResponse& from); + SubmitCommandResponse(::google::protobuf::Arena* arena, SubmitCommandResponse&& from) noexcept + : SubmitCommandResponse(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); + static const ::google::protobuf::internal::ClassDataFull _class_data_; + + public: + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kPbOutFieldNumber = 1, + }; + // bytes pbOut = 1; + void clear_pbout() ; + const std::string& pbout() const; + template + void set_pbout(Arg_&& arg, Args_... args); + std::string* mutable_pbout(); + PROTOBUF_NODISCARD std::string* release_pbout(); + void set_allocated_pbout(std::string* value); + + private: + const std::string& _internal_pbout() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_pbout( + const std::string& value); + std::string* _internal_mutable_pbout(); + + public: + // @@protoc_insertion_point(class_scope:leechrpc.SubmitCommandResponse) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 0, 1, 0, + 0, 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from, + const SubmitCommandResponse& from_msg); + ::google::protobuf::internal::ArenaStringPtr pbout_; + ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_leechgrpc_2eproto; +}; +// ------------------------------------------------------------------- + +class SubmitCommandRequest final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:leechrpc.SubmitCommandRequest) */ { + public: + inline SubmitCommandRequest() : SubmitCommandRequest(nullptr) {} + ~SubmitCommandRequest() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(SubmitCommandRequest* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(SubmitCommandRequest)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR SubmitCommandRequest( + ::google::protobuf::internal::ConstantInitialized); + + inline SubmitCommandRequest(const SubmitCommandRequest& from) : SubmitCommandRequest(nullptr, from) {} + inline SubmitCommandRequest(SubmitCommandRequest&& from) noexcept + : SubmitCommandRequest(nullptr, std::move(from)) {} + inline SubmitCommandRequest& operator=(const SubmitCommandRequest& from) { + CopyFrom(from); + return *this; + } + inline SubmitCommandRequest& operator=(SubmitCommandRequest&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const SubmitCommandRequest& default_instance() { + return *internal_default_instance(); + } + static inline const SubmitCommandRequest* internal_default_instance() { + return reinterpret_cast( + &_SubmitCommandRequest_default_instance_); + } + static constexpr int kIndexInFileMessages = 0; + friend void swap(SubmitCommandRequest& a, SubmitCommandRequest& b) { a.Swap(&b); } + inline void Swap(SubmitCommandRequest* other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SubmitCommandRequest* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + SubmitCommandRequest* New(::google::protobuf::Arena* arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const SubmitCommandRequest& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const SubmitCommandRequest& from) { SubmitCommandRequest::MergeImpl(*this, from); } + + private: + static void MergeImpl( + ::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(SubmitCommandRequest* other); + private: + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "leechrpc.SubmitCommandRequest"; } + + protected: + explicit SubmitCommandRequest(::google::protobuf::Arena* arena); + SubmitCommandRequest(::google::protobuf::Arena* arena, const SubmitCommandRequest& from); + SubmitCommandRequest(::google::protobuf::Arena* arena, SubmitCommandRequest&& from) noexcept + : SubmitCommandRequest(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); + static const ::google::protobuf::internal::ClassDataFull _class_data_; + + public: + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kPbInFieldNumber = 1, + }; + // bytes pbIn = 1; + void clear_pbin() ; + const std::string& pbin() const; + template + void set_pbin(Arg_&& arg, Args_... args); + std::string* mutable_pbin(); + PROTOBUF_NODISCARD std::string* release_pbin(); + void set_allocated_pbin(std::string* value); + + private: + const std::string& _internal_pbin() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_pbin( + const std::string& value); + std::string* _internal_mutable_pbin(); + + public: + // @@protoc_insertion_point(class_scope:leechrpc.SubmitCommandRequest) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 0, 1, 0, + 0, 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from, + const SubmitCommandRequest& from_msg); + ::google::protobuf::internal::ArenaStringPtr pbin_; + ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_leechgrpc_2eproto; +}; + +// =================================================================== + + + + +// =================================================================== + + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// SubmitCommandRequest + +// bytes pbIn = 1; +inline void SubmitCommandRequest::clear_pbin() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.pbin_.ClearToEmpty(); +} +inline const std::string& SubmitCommandRequest::pbin() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:leechrpc.SubmitCommandRequest.pbIn) + return _internal_pbin(); +} +template +inline PROTOBUF_ALWAYS_INLINE void SubmitCommandRequest::set_pbin(Arg_&& arg, + Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.pbin_.SetBytes(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:leechrpc.SubmitCommandRequest.pbIn) +} +inline std::string* SubmitCommandRequest::mutable_pbin() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_pbin(); + // @@protoc_insertion_point(field_mutable:leechrpc.SubmitCommandRequest.pbIn) + return _s; +} +inline const std::string& SubmitCommandRequest::_internal_pbin() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.pbin_.Get(); +} +inline void SubmitCommandRequest::_internal_set_pbin(const std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.pbin_.Set(value, GetArena()); +} +inline std::string* SubmitCommandRequest::_internal_mutable_pbin() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.pbin_.Mutable( GetArena()); +} +inline std::string* SubmitCommandRequest::release_pbin() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:leechrpc.SubmitCommandRequest.pbIn) + return _impl_.pbin_.Release(); +} +inline void SubmitCommandRequest::set_allocated_pbin(std::string* value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.pbin_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.pbin_.IsDefault()) { + _impl_.pbin_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:leechrpc.SubmitCommandRequest.pbIn) +} + +// ------------------------------------------------------------------- + +// SubmitCommandResponse + +// bytes pbOut = 1; +inline void SubmitCommandResponse::clear_pbout() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.pbout_.ClearToEmpty(); +} +inline const std::string& SubmitCommandResponse::pbout() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:leechrpc.SubmitCommandResponse.pbOut) + return _internal_pbout(); +} +template +inline PROTOBUF_ALWAYS_INLINE void SubmitCommandResponse::set_pbout(Arg_&& arg, + Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.pbout_.SetBytes(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:leechrpc.SubmitCommandResponse.pbOut) +} +inline std::string* SubmitCommandResponse::mutable_pbout() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_pbout(); + // @@protoc_insertion_point(field_mutable:leechrpc.SubmitCommandResponse.pbOut) + return _s; +} +inline const std::string& SubmitCommandResponse::_internal_pbout() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.pbout_.Get(); +} +inline void SubmitCommandResponse::_internal_set_pbout(const std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.pbout_.Set(value, GetArena()); +} +inline std::string* SubmitCommandResponse::_internal_mutable_pbout() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.pbout_.Mutable( GetArena()); +} +inline std::string* SubmitCommandResponse::release_pbout() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:leechrpc.SubmitCommandResponse.pbOut) + return _impl_.pbout_.Release(); +} +inline void SubmitCommandResponse::set_allocated_pbout(std::string* value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.pbout_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.pbout_.IsDefault()) { + _impl_.pbout_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:leechrpc.SubmitCommandResponse.pbOut) +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) +} // namespace leechrpc + + +// @@protoc_insertion_point(global_scope) + +#include "google/protobuf/port_undef.inc" + +#endif // leechgrpc_2eproto_2epb_2eh diff --git a/libleechgrpc/leechgrpc.h b/libleechgrpc/leechgrpc.h new file mode 100644 index 0000000..f248d77 --- /dev/null +++ b/libleechgrpc/leechgrpc.h @@ -0,0 +1,354 @@ +// leechgrpc.h : external header of the libleechgrpc library. +// +// libleechgrpc is a library used by LeechCore to communicate with a LeechAgent +// gRPC server. The library provides functions to create a gRPC client and +// server, submit commands to the server, and handle incoming commands. +// +// libleechgrpc offers a platform-independent way to communicate with remote +// LeechAgent instances, using gRPC as the underlying communication protocol. +// The library supports both insecure and secure connections, with secure +// connections using mTLS. +// +// For more information visit the project page at: +// https://github.com/ufrisk/libleechgrpc +// +// (c) Ulf Frisk, 2025 +// Author: Ulf Frisk, pcileech@frizk.net +// + +#ifndef __LEECHGRPC_H__ +#define __LEECHGRPC_H__ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define LEECHGRPC_MESSAGE_SIZE_MAX (64*1024*1024) +#define LEECHGRPC_CLIENT_TIMEOUT_MS (5000) + +#ifdef _WIN32 + +#include +#define LEECHGRPC_EXPORTED_FUNCTION __declspec(dllexport) + +#endif /* _WIN32 */ +#if defined(LINUX) || defined(MACOS) + +#include +#include +#define LEECHGRPC_EXPORTED_FUNCTION __attribute__((visibility("default"))) +typedef void VOID, *PVOID, *HANDLE; +typedef size_t SIZE_T; +typedef uint32_t DWORD, BOOL; +typedef uint8_t BYTE, *PBYTE; +typedef char CHAR, *LPSTR; +typedef const char *LPCSTR; +#define _Success_(x) +#define _In_ +#define _Out_ +#define _In_opt_ + +#endif /* LINUX || MACOS */ + +typedef void *LEECHGRPC_CLIENT_HANDLE, *LEECHGRPC_SERVER_HANDLE; + + + +//----------------------------------------------------------------------------- +// LeechgRPC Client API: +//----------------------------------------------------------------------------- + +/* +* Submit a command to the gRPC server. +* -- hGRPC: Handle to the gRPC client. +* -- pbIn: Pointer to the input buffer. +* -- cbIn: Size of the input buffer. +* -- ppbOut: Pointer to receive the output buffer. The caller is responsible for freeing this buffer with LocalFree/free. +* -- pcbOut: Pointer to receive the size of the output buffer. +* -- return: TRUE if the command was successfully submitted; otherwise, FALSE. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return) +BOOL leechgrpc_client_submit_command( + _In_ LEECHGRPC_CLIENT_HANDLE hGRPC, + _In_ PBYTE pbIn, + _In_ SIZE_T cbIn, + _Out_ PBYTE *ppbOut, + _Out_ SIZE_T *pcbOut +); + +typedef BOOL(*pfn_leechgrpc_client_submit_command)( + _In_ LEECHGRPC_CLIENT_HANDLE hGRPC, + _In_ PBYTE pbIn, + _In_ SIZE_T cbIn, + _Out_ PBYTE *ppbOut, + _Out_ SIZE_T *pcbOut +); + +/* +* Free the gRPC client connection. +* -- hGRPC: Handle to the gRPC client. +*/ +LEECHGRPC_EXPORTED_FUNCTION +VOID leechgrpc_client_free( + _In_ LEECHGRPC_CLIENT_HANDLE hGRPC +); + +typedef VOID(*pfn_leechgrpc_client_free)( + _In_ LEECHGRPC_CLIENT_HANDLE hGRPC +); + +/* +* Create an insecure unauthenticated unencrypted gRPC client connection to the gRPC server. +* -- pszAddress: Address of the gRPC server. +* -- dwPort: Port of the gRPC server. +* -- return: Handle to the gRPC client connection, or NULL on failure. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_CLIENT_HANDLE leechgrpc_client_create_insecure( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort +); + +typedef LEECHGRPC_CLIENT_HANDLE(*pfn_leechgrpc_client_create_insecure)( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort +); + +/* +* Create a gRPC client connection to the gRPC server with mTLS. +* -- pszAddress: Address of the gRPC server. +* -- dwPort: Port of the gRPC server. +* -- szTlsServerHostnameOverride: Optional hostname to verify against the server certificate (if different from address). +* -- szTlsServerCertPath: Server CA certificate to trust for mTLS connections. +* -- szTlsClientP12Path: Path to the client's TLS certificate (incl. chain) & private key (.p12 / .pfx). +* -- szTlsClientP12Password: Password for the client's TLS certificate & private key (.p12 / .pfx). +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_CLIENT_HANDLE leechgrpc_client_create_secure_p12( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ LPCSTR szTlsServerHostnameOverride, + _In_opt_ LPCSTR szTlsServerCertPath, + _In_ LPCSTR szTlsClientP12Path, + _In_ LPCSTR szTlsClientP12Password +); + +typedef LEECHGRPC_CLIENT_HANDLE(*pfn_leechgrpc_client_create_secure_p12)( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ LPCSTR szTlsServerHostnameOverride, + _In_opt_ LPCSTR szTlsServerCertPath, + _In_ LPCSTR szTlsClientP12Path, + _In_ LPCSTR szTlsClientP12Password +); + +/* +* Create a gRPC client connection to the gRPC server with mTLS. +* -- pszAddress: Address of the gRPC server. +* -- dwPort: Port of the gRPC server. +* -- szTlsServerHostnameOverride: Optional hostname to verify against the server certificate (if different from address). +* -- szTlsServerCert: Server CA certificate to trust for mTLS connections. +* -- szTlsClientCert: Cerver TLS certificate. +* -- szTlsClientCertPrivateKey: Client TLS certificate private key. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_CLIENT_HANDLE leechgrpc_client_create_secure_pemraw( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ LPCSTR szTlsServerHostnameOverride, + _In_opt_ LPCSTR szTlsServerCert, + _In_ LPCSTR szTlsClientCert, + _In_ LPCSTR szTlsClientCertPrivateKey +); + +typedef LEECHGRPC_CLIENT_HANDLE(*pfn_leechgrpc_client_create_secure_pemraw)( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ LPCSTR szTlsServerHostnameOverride, + _In_opt_ LPCSTR szTlsServerCert, + _In_ LPCSTR szTlsClientCert, + _In_ LPCSTR szTlsClientCertPrivateKey +); + +/* +* Create a gRPC client connection to the gRPC server with mTLS. +* -- pszAddress: Address of the gRPC server. +* -- dwPort: Port of the gRPC server. +* -- szTlsServerHostnameOverride: Optional hostname to verify against the server certificate (if different from address). +* -- szTlsServerCertPath: Server CA certificate to trust for mTLS connections. +* -- szTlsClientCertPath: Cerver TLS certificate. +* -- szTlsClientCertPrivateKeyPath: Client TLS certificate private key. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_CLIENT_HANDLE leechgrpc_client_create_secure_pemfile( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ LPCSTR szTlsServerHostnameOverride, + _In_opt_ LPCSTR szTlsServerCertPath, + _In_ LPCSTR szTlsClientCertPath, + _In_ LPCSTR szTlsClientCertPrivateKeyPath +); + +typedef LEECHGRPC_CLIENT_HANDLE(*pfn_leechgrpc_client_create_secure_pemfile)( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ LPCSTR szTlsServerHostnameOverride, + _In_opt_ LPCSTR szTlsServerCertPath, + _In_ LPCSTR szTlsClientCertPath, + _In_ LPCSTR szTlsClientCertPrivateKeyPath +); + + + +//----------------------------------------------------------------------------- +// LeechgRPC Server API: +//----------------------------------------------------------------------------- + +/* +* Callback function used to pass on a command received by the gRPC server. +* -- pbIn: Pointer to the input buffer. +* -- cbIn: Size of the input buffer. +* -- ppbOut: Pointer to receive the output buffer allocated by the callback function, freed by the caller. +* -- pcbOut: Pointer to receive the size of the output buffer. +*/ +typedef VOID(*PFN_RESERVED_SUBMIT_COMMAND_CB)(_In_opt_ PVOID ctx, _In_ PBYTE pbIn, _In_ SIZE_T cbIn, _Out_ PBYTE *ppbOut, _Out_ SIZE_T *pcbOut); + +/* +* Wait for the gRPC server to shutdown. +* -- hGRPC: Handle to the gRPC server. +*/ +LEECHGRPC_EXPORTED_FUNCTION +VOID leechgrpc_server_wait(_In_ LEECHGRPC_SERVER_HANDLE hGRPC); + +typedef VOID(*pfn_leechgrpc_server_wait)(_In_ LEECHGRPC_SERVER_HANDLE hGRPC); + +/* +* Shut down the gRPC server. +* -- hGRPC: Handle to the gRPC server. +*/ +LEECHGRPC_EXPORTED_FUNCTION +VOID leechgrpc_server_shutdown(_In_ LEECHGRPC_SERVER_HANDLE hGRPC); + +typedef VOID(*pfn_leechgrpc_server_shutdown)(_In_ LEECHGRPC_SERVER_HANDLE hGRPC); + +/* +* Create an insecure gRPC server without any authentication / encryption. +* -- szAddress: Address to listen on, e.g., "localhost" or "0.0.0.0". +* -- dwPort: Port to listen on. +* -- pfnReservedSubmitCommandCB: Callback function to handle incoming commands. +* -- return: Handle to the gRPC server, or NULL on failure. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_SERVER_HANDLE leechgrpc_server_create_insecure( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB +); + +typedef LEECHGRPC_SERVER_HANDLE(*pfn_leechgrpc_server_create_insecure)( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB +); + +/* +* Create a gRPC server with mTLS. +* -- szAddress: Address to listen on, e.g., "localhost" or " +* -- dwPort: Port to listen on. +* -- ctx: Optional context to pass to the callback function. +* -- pfnReservedSubmitCommandCB: Callback function to handle incoming commands. +* -- szTlsClientCertPath: Client CA certificate to trust for mTLS connections. +* -- szTlsServerP12Path: Path to the server's TLS certificate (incl. chain) & private key (.p12 / .pfx). +* -- szTlsServerP12Password: Password for the server's TLS certificate & private key (.p12 / .pfx). +* -- return: Handle to the gRPC server, or NULL on failure. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_SERVER_HANDLE leechgrpc_server_create_secure_p12( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB, + _In_ LPCSTR szTlsClientCertPath, + _In_ LPCSTR szTlsServerP12Path, + _In_ LPCSTR szTlsServerP12Password +); + +typedef LEECHGRPC_SERVER_HANDLE(*pfn_leechgrpc_server_create_secure_p12)( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB, + _In_ LPCSTR szTlsClientCertPath, + _In_ LPCSTR szTlsServerP12Path, + _In_ LPCSTR szTlsServerP12Password +); + +/* +* Create a gRPC server with mTLS. +* -- szAddress: Address to listen on, e.g., "localhost" or " +* -- dwPort: Port to listen on. +* -- ctx: Optional context to pass to the callback function. +* -- pfnReservedSubmitCommandCB: Callback function to handle incoming commands. +* -- szTlsClientCert: Client CA certificate to trust for mTLS connections. +* -- szTlsServerCert: Server TLS certificate (incl. chain). +* -- szTlsServerCertPrivateKey: Server TLS certificate private key. +* -- return: Handle to the gRPC server, or NULL on failure. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_SERVER_HANDLE leechgrpc_server_create_secure_pemraw( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB, + _In_ LPCSTR szTlsClientCert, + _In_ LPCSTR szTlsServerCert, + _In_ LPCSTR szTlsServerCertPrivateKey +); + +typedef LEECHGRPC_SERVER_HANDLE(*pfn_leechgrpc_server_create_secure_pemraw)( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB, + _In_ LPCSTR szTlsClientCert, + _In_ LPCSTR szTlsServerCert, + _In_ LPCSTR szTlsServerCertPrivateKey +); + +/* +* Create a gRPC server with mTLS. +* -- szAddress: Address to listen on, e.g., "localhost" or " +* -- dwPort: Port to listen on. +* -- ctx: Optional context to pass to the callback function. +* -- pfnReservedSubmitCommandCB: Callback function to handle incoming commands. +* -- szTlsClientCertPath: Client CA certificate to trust for mTLS connections. +* -- szTlsServerCertPath: Server TLS certificate (incl. chain). +* -- szTlsServerCertPrivateKeyPath: Server TLS certificate private key. +* -- return: Handle to the gRPC server, or NULL on failure. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_SERVER_HANDLE leechgrpc_server_create_secure_pemfile( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB, + _In_ LPCSTR szTlsClientCertPath, + _In_ LPCSTR szTlsServerCertPath, + _In_ LPCSTR szTlsServerCertPrivateKeyPath +); + +typedef LEECHGRPC_SERVER_HANDLE(*pfn_leechgrpc_server_create_secure_pemfile)( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB, + _In_ LPCSTR szTlsClientCertPath, + _In_ LPCSTR szTlsServerCertPath, + _In_ LPCSTR szTlsServerCertPrivateKeyPath +); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __LEECHGRPC_H__ */ diff --git a/libleechgrpc/leechgrpc_client.cc b/libleechgrpc/leechgrpc_client.cc new file mode 100644 index 0000000..889ef04 --- /dev/null +++ b/libleechgrpc/leechgrpc_client.cc @@ -0,0 +1,294 @@ +#include +#include +#include +#include + +// Include the generated headers. +#ifdef _WIN32 +#include "generated/leechgrpc.grpc.pb.h" +#include "generated/leechgrpc.pb.h" +#else +#include "leechgrpc.grpc.pb.h" +#include "leechgrpc.pb.h" +#endif /* _WIN32 */ + +#include "leechgrpc.h" +#include "oscompatibility.h" +#include "util.h" + +using grpc::Channel; +using grpc::ClientContext; +using grpc::Status; +using leechrpc::LeechRpc; +using leechrpc::SubmitCommandRequest; +using leechrpc::SubmitCommandResponse; + +// A client class that connects to the LeechRpc server +class LeechRpcClient { +public: + // Constructor: create a new Stub connected to the provided channel + explicit LeechRpcClient(std::shared_ptr channel) : stub_(LeechRpc::NewStub(channel)) {} + + // Calls the ReservedSubmitCommand RPC + std::string ReservedSubmitCommand(const std::string& message) + { + // Container for the request and response + SubmitCommandRequest request; + SubmitCommandResponse response; + + // Fill the request with the client data + request.set_pbin(message); + + // Context for the client (can set metadata, etc.) + ClientContext context; + + // Set a deadline for the RPC + auto deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(LEECHGRPC_CLIENT_TIMEOUT_MS); + context.set_deadline(deadline); + + // The actual RPC + Status status = stub_->ReservedSubmitCommand(&context, request, &response); + + // Act upon its status + if (!status.ok()) { + //std::cerr << "[Client] RPC failed: " << status.error_message() << std::endl; + return ""; + } + + // Return the pbOut bytes as a std::string + return response.pbout(); + } + +private: + // Stub used for making RPC calls + std::unique_ptr stub_; +}; + +/* +* Submit a command to the gRPC server. +* -- hGRPC: Handle to the gRPC client. +* -- pbIn: Pointer to the input buffer. +* -- cbIn: Size of the input buffer. +* -- ppbOut: Pointer to receive the output buffer. The caller is responsible for freeing this buffer with LocalFree/free. +* -- pcbOut: Pointer to receive the size of the output buffer. +* -- return: TRUE if the command was successfully submitted; otherwise, FALSE. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return) +BOOL leechgrpc_client_submit_command( + _In_ LEECHGRPC_CLIENT_HANDLE hGRPC, + _In_ PBYTE pbIn, + _In_ SIZE_T cbIn, + _Out_ PBYTE *ppbOut, + _Out_ SIZE_T *pcbOut +) +{ + try { + // Cast the handle to a client + LeechRpcClient *client = static_cast(hGRPC); + // Call the ReservedSubmitCommand RPC + std::string message(reinterpret_cast(pbIn), cbIn); + std::string reply = client->ReservedSubmitCommand(message); + // Allocate memory for the response + *ppbOut = reinterpret_cast(LocalAlloc(LMEM_ZEROINIT, reply.size())); + if(*ppbOut == NULL) { + std::cerr << "[Client] Error allocating memory for response" << std::endl; + return FALSE; + } + if(reply.size() == 0) { + std::cerr << "[Client] Error submitting command" << std::endl; + return FALSE; + } + // Copy the response to the output buffer + memcpy(*ppbOut, reply.c_str(), reply.size()); + *pcbOut = reply.size(); + return TRUE; + } catch(const std::exception &e) { + std::cerr << "[Client] Error submitting command: " << e.what() << std::endl; + return FALSE; + } +} + +/* +* Create a gRPC client connection to the gRPC server. +* -- pszAddress: Address of the gRPC server. +* -- dwPort: Port of the gRPC server. +* -- return: Handle to the gRPC client connection, or NULL on failure. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_CLIENT_HANDLE leechgrpc_client_create_insecure( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort +) { + try { + std::string address = std::string(szAddress) + ":" + std::to_string(dwPort); + grpc::ChannelArguments channel_args; + channel_args.SetMaxReceiveMessageSize(LEECHGRPC_MESSAGE_SIZE_MAX); + channel_args.SetMaxSendMessageSize(LEECHGRPC_MESSAGE_SIZE_MAX); + channel_args.SetSslTargetNameOverride("*"); + return reinterpret_cast(new LeechRpcClient(grpc::CreateCustomChannel(address, grpc::InsecureChannelCredentials(), channel_args))); + } catch(const std::exception &e) { + std::cerr << "[Client] Error creating channel: " << e.what() << std::endl; + return NULL; + } +} + +_Success_(return != NULL) +LEECHGRPC_CLIENT_HANDLE leechgrpc_client_create_secure_internal( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ LPCSTR szTlsServerHostnameOverride, + _In_ const std::string sTlsServerCert, + _In_ const std::string sTlsClientCert, + _In_ const std::string sTlsClientCertPrivateKey +) { + try { + if(sTlsClientCert.length() < 8 || sTlsClientCertPrivateKey.length() < 8) { + std::cerr << "[Client] Invalid TLS certificate or key provided." << std::endl; + return NULL; + } + // address/port -> string: + CHAR szAddressAndPort[MAX_PATH] = { 0 }; + _snprintf_s(szAddressAndPort, MAX_PATH, _TRUNCATE, "%s:%u", szAddress, dwPort); + const std::string server_address(szAddressAndPort); + // mTLS server cert & client cert/key: + grpc::SslCredentialsOptions sslOpts; + if(sTlsServerCert.length() > 8) { + sslOpts.pem_root_certs = sTlsServerCert; + } + sslOpts.pem_private_key = sTlsClientCertPrivateKey; + sslOpts.pem_cert_chain = sTlsClientCert; + // build and configure server: + grpc::ChannelArguments channelArgs; + channelArgs.SetMaxReceiveMessageSize(LEECHGRPC_MESSAGE_SIZE_MAX); + channelArgs.SetMaxSendMessageSize(LEECHGRPC_MESSAGE_SIZE_MAX); + if(szTlsServerHostnameOverride) { + channelArgs.SetSslTargetNameOverride(szTlsServerHostnameOverride); + } + auto creds = grpc::SslCredentials(sslOpts); + auto channel = grpc::CreateCustomChannel(server_address, creds, channelArgs); + if(!channel) { + std::cerr << "[Client] Error creating secure channel to: " << server_address << std::endl; + return NULL; + } + // create and return a new LeechRpcClient object, cast to LEECHGRPC_CLIENT_HANDLE: + // caller is responsible for deleting this pointer. + return reinterpret_cast(new LeechRpcClient(channel)); + } catch(const std::exception &e) { + std::cerr << "[Client] Exception in secure client creation: " << e.what() << std::endl; + return NULL; + } catch(...) { + std::cerr << "[Client] Unknown error in secure client creation." << std::endl; + return NULL; + } +} + +/* +* Create a gRPC client connection to the gRPC server with mTLS. +* -- pszAddress: Address of the gRPC server. +* -- dwPort: Port of the gRPC server. +* -- szTlsServerHostnameOverride: Optional hostname to verify against the server certificate (if different from address). +* -- szTlsServerCertPath: Server CA certificate to trust for mTLS connections. +* -- szTlsClientP12Path: Path to the client's TLS certificate (incl. chain) & private key (.p12 / .pfx). +* -- szTlsClientP12Password: Password for the client's TLS certificate & private key (.p12 / .pfx). +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_CLIENT_HANDLE leechgrpc_client_create_secure_p12( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ LPCSTR szTlsServerHostnameOverride, + _In_opt_ LPCSTR szTlsServerCertPath, + _In_ LPCSTR szTlsClientP12Path, + _In_ LPCSTR szTlsClientP12Password +) { + std::string sTlsServerCert(""); + std::string sTlsClientCert; + std::string sTlsClientCertPrivateKey; + if(szTlsServerCertPath) { + if(!Util_LoadCaPemFromFile(szTlsServerCertPath, sTlsServerCert)) { + std::cerr << "[Client] Failed to load root CA from file: " << szTlsServerCertPath << std::endl; + return NULL; + } + } + if(!Util_LoadPemFromPkcs12(szTlsClientP12Path, szTlsClientP12Password, sTlsClientCertPrivateKey, sTlsClientCert)) { + std::cerr << "[Client] Failed to load client cert/key from: " << szTlsClientP12Path << std::endl; + return NULL; + } + return leechgrpc_client_create_secure_internal(szAddress, dwPort, szTlsServerHostnameOverride, sTlsServerCert, sTlsClientCert, sTlsClientCertPrivateKey); +} + +/* +* Create a gRPC client connection to the gRPC server with mTLS. +* -- pszAddress: Address of the gRPC server. +* -- dwPort: Port of the gRPC server. +* -- szTlsServerHostnameOverride: Optional hostname to verify against the server certificate (if different from address). +* -- szTlsServerCert: Server CA certificate to trust for mTLS connections. +* -- szTlsClientCert: Cerver TLS certificate. +* -- szTlsClientCertPrivateKey: Client TLS certificate private key. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_CLIENT_HANDLE leechgrpc_client_create_secure_pemraw( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ LPCSTR szTlsServerHostnameOverride, + _In_opt_ LPCSTR szTlsServerCert, + _In_ LPCSTR szTlsClientCert, + _In_ LPCSTR szTlsClientCertPrivateKey +) { + const std::string sTlsServerCertNull(""); + const std::string sTlsServerCert(szTlsServerCert); + const std::string sTlsClientCert(szTlsClientCert); + const std::string sTlsClientCertPrivateKey(szTlsClientCertPrivateKey); + return leechgrpc_client_create_secure_internal(szAddress, dwPort, szTlsServerHostnameOverride, (szTlsServerCert ? sTlsServerCert : sTlsServerCertNull), sTlsClientCert, sTlsClientCertPrivateKey); +} + +/* +* Create a gRPC client connection to the gRPC server with mTLS. +* -- pszAddress: Address of the gRPC server. +* -- dwPort: Port of the gRPC server. +* -- szTlsServerHostnameOverride: Optional hostname to verify against the server certificate (if different from address). +* -- szTlsServerCertPath: Server CA certificate to trust for mTLS connections. +* -- szTlsClientCertPath: Cerver TLS certificate. +* -- szTlsClientCertPrivateKeyPath: Client TLS certificate private key. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_CLIENT_HANDLE leechgrpc_client_create_secure_pemfile( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ LPCSTR szTlsServerHostnameOverride, + _In_opt_ LPCSTR szTlsServerCertPath, + _In_ LPCSTR szTlsClientCertPath, + _In_ LPCSTR szTlsClientCertPrivateKeyPath +) { + std::string sTlsServerCert(""); + std::string sTlsClientCert; + std::string sTlsClientCertPrivateKey; + if(szTlsServerCertPath) { + if(!Util_LoadCaPemFromFile(szTlsServerCertPath, sTlsServerCert)) { + std::cerr << "[Client] Failed to load server ca certificate from file: " << szTlsServerCertPath << std::endl; + return NULL; + } + } + if(!Util_LoadCaPemFromFile(szTlsClientCertPath, sTlsClientCert)) { + std::cerr << "[Client] Failed to load client certificate from file: " << szTlsClientCertPath << std::endl; + return NULL; + } + if(!Util_LoadCaPemFromFile(szTlsClientCertPrivateKeyPath, sTlsClientCertPrivateKey)) { + std::cerr << "[Client] Failed to load client certificate private key from file: " << szTlsClientCertPrivateKeyPath << std::endl; + return NULL; + } + return leechgrpc_client_create_secure_internal(szAddress, dwPort, szTlsServerHostnameOverride, sTlsServerCert, sTlsClientCert, sTlsClientCertPrivateKey); +} + +/* +* Free the gRPC client connection. +* -- hGRPC: Handle to the gRPC client. +*/ +LEECHGRPC_EXPORTED_FUNCTION +VOID leechgrpc_client_free(_In_ LEECHGRPC_CLIENT_HANDLE hGRPC) +{ + try { + delete static_cast(hGRPC); + } catch(const std::exception &e) { + std::cerr << "[Client] Error free client: " << e.what() << std::endl; + } +} diff --git a/libleechgrpc/leechgrpc_server.cc b/libleechgrpc/leechgrpc_server.cc new file mode 100644 index 0000000..4ae0f6e --- /dev/null +++ b/libleechgrpc/leechgrpc_server.cc @@ -0,0 +1,279 @@ +#include +#include +#include +#include +#include +#include + +// Include the generated headers. +#ifdef _WIN32 +#include "generated/leechgrpc.grpc.pb.h" +#include "generated/leechgrpc.pb.h" +#else +#include "leechgrpc.grpc.pb.h" +#include "leechgrpc.pb.h" +#endif /* _WIN32 */ + +#include "leechgrpc.h" +#include "oscompatibility.h" +#include "util.h" + +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::Status; +using leechrpc::LeechRpc; +using leechrpc::SubmitCommandRequest; +using leechrpc::SubmitCommandResponse; + +// Implementation of the LeechRpc service. +class LeechRpcServiceImpl final : public LeechRpc::Service { +public: + explicit LeechRpcServiceImpl(PVOID ctx, PFN_RESERVED_SUBMIT_COMMAND_CB pfnCB) : m_ctx(ctx), m_pfnCB(pfnCB) + { + } + + // Handle the ReservedSubmitCommand RPC. + Status ReservedSubmitCommand(ServerContext *context, const SubmitCommandRequest *request, SubmitCommandResponse *response) override + { + // Extract the client’s message (pbIn) + const std::string client_data = request->pbin(); + const PBYTE pbIn = reinterpret_cast(const_cast(client_data.data())); + SIZE_T cbIn = client_data.size(); + + // Call the callback function + PBYTE pbOut = NULL; + SIZE_T cbOut = 0; + m_pfnCB(m_ctx, pbIn, cbIn, &pbOut, &cbOut); + + // Set the response message & free it. + response->set_pbout(reinterpret_cast(pbOut), cbOut); + LocalFree(pbOut); + + return Status::OK; + } + +private: + PVOID m_ctx; + PFN_RESERVED_SUBMIT_COMMAND_CB m_pfnCB; +}; + +/* +* Create a gRPC server. +* -- dwPort: Port to listen on. +* -- pfnReservedSubmitCommandCB: Callback function to handle incoming commands. +* -- return: Handle to the gRPC server, or NULL on failure. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +HANDLE leechgrpc_server_create_insecure( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB +) { + auto *service = new LeechRpcServiceImpl(ctx, pfnReservedSubmitCommandCB); + // Convert the address/port to a string + CHAR szAddressAndPort[MAX_PATH] = { 0 }; + _snprintf_s(szAddressAndPort, MAX_PATH, _TRUNCATE, "%s:%d", szAddress, dwPort); + const std::string server_address(szAddressAndPort); + // Build the server + ServerBuilder builder; + builder.SetMaxReceiveMessageSize(LEECHGRPC_MESSAGE_SIZE_MAX); + builder.SetMaxSendMessageSize(LEECHGRPC_MESSAGE_SIZE_MAX); + // Listen on the given address without any authentication mechanism (Insecure) + builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); + // Register our service + builder.RegisterService(service); + // Assemble the server + std::unique_ptr server = builder.BuildAndStart(); + if(!server) { + return NULL; + } + // Dynamically allocate a unique_ptr on the heap + std::unique_ptr> ptrOnHeap(new std::unique_ptr(std::move(server))); + // Transfer ownership by returning the raw pointer as HANDLE + // The caller will store this handle and cast it back later. + return reinterpret_cast(ptrOnHeap.release()); +} + +_Success_(return != NULL) +LEECHGRPC_SERVER_HANDLE leechgrpc_server_create_secure_internal( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB, + _In_ const std::string sTlsClientCert, + _In_ const std::string sTlsServerCert, + _In_ const std::string sTlsServerCertPrivateKey +) { + try { + if(sTlsClientCert.length() < 8 || sTlsServerCert.length() < 8 || sTlsServerCertPrivateKey.length() < 8) { + std::cerr << "[Server] Invalid TLS certificate or key provided." << std::endl; + return NULL; + } + auto *service = new LeechRpcServiceImpl(ctx, pfnReservedSubmitCommandCB); + // address/port -> string: + CHAR szAddressAndPort[MAX_PATH] = { 0 }; + _snprintf_s(szAddressAndPort, MAX_PATH, _TRUNCATE, "%s:%u", szAddress, dwPort); + const std::string server_address(szAddressAndPort); + // mTLS client cert & server cert/key: + grpc::SslServerCredentialsOptions::PemKeyCertPair keyCertPair; + keyCertPair.private_key = sTlsServerCertPrivateKey; + keyCertPair.cert_chain = sTlsServerCert; + grpc::SslServerCredentialsOptions sslOpts; + sslOpts.pem_key_cert_pairs.push_back(keyCertPair); + sslOpts.pem_root_certs = sTlsClientCert; + sslOpts.client_certificate_request = GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY; + // build and configure server: + auto serverCreds = grpc::SslServerCredentials(sslOpts); + grpc::ServerBuilder builder; + builder.SetMaxReceiveMessageSize(LEECHGRPC_MESSAGE_SIZE_MAX); + builder.SetMaxSendMessageSize(LEECHGRPC_MESSAGE_SIZE_MAX); + builder.AddListeningPort(server_address, serverCreds); + builder.RegisterService(service); + // start the server: + std::unique_ptr server = builder.BuildAndStart(); + if(!server) { + std::cerr << "[Server] Failed to start secure server on: " << server_address << std::endl; + return NULL; + } + // dynamically allocate a unique_ptr on the heap: + std::unique_ptr> ptrOnHeap(new std::unique_ptr(std::move(server))); + // return the raw pointer as a LEECHGRPC_SERVER_HANDLE. + // caller is responsible for cleanup. + return reinterpret_cast(ptrOnHeap.release()); + } catch(const std::exception &ex) { + std::cerr << "[Server] Exception in secure server creation: " << ex.what() << std::endl; + return NULL; + } catch(...) { + std::cerr << "[Server] Unknown error in secure server creation." << std::endl; + return NULL; + } +} + +/* +* Create a gRPC server with mTLS. +* -- szAddress: Address to listen on, e.g., "localhost" or " +* -- dwPort: Port to listen on. +* -- ctx: Optional context to pass to the callback function. +* -- pfnReservedSubmitCommandCB: Callback function to handle incoming commands. +* -- szTlsClientCert: Client CA certificate to trust for mTLS connections. +* -- szTlsServerCert: Server TLS certificate (incl. chain). +* -- szTlsServerCertPrivateKey: Server TLS certificate private key. +* -- return: Handle to the gRPC server, or NULL on failure. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_SERVER_HANDLE leechgrpc_server_create_secure_pemraw( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB, + _In_ LPCSTR szTlsClientCert, + _In_ LPCSTR szTlsServerCert, + _In_ LPCSTR szTlsServerCertPrivateKey +) { + const std::string sTlsClientCert(szTlsClientCert); + const std::string sTlsServerCert(szTlsServerCert); + const std::string sTlsServerCertPrivateKey(szTlsServerCertPrivateKey); + return leechgrpc_server_create_secure_internal(szAddress, dwPort, ctx, pfnReservedSubmitCommandCB, sTlsClientCert, sTlsServerCert, sTlsServerCertPrivateKey); +} + +/* +* Create a gRPC server with mTLS. +* -- szAddress: Address to listen on, e.g., "localhost" or " +* -- dwPort: Port to listen on. +* -- ctx: Optional context to pass to the callback function. +* -- pfnReservedSubmitCommandCB: Callback function to handle incoming commands. +* -- szTlsClientCertPath: Client CA certificate to trust for mTLS connections. +* -- szTlsServerP12Path: Path to the server's TLS certificate & private key (.p12 / .pfx). +* -- szTlsServerP12Password: Password for the server's TLS certificate & private key (.p12 / .pfx). +* -- return: Handle to the gRPC server, or NULL on failure. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_SERVER_HANDLE leechgrpc_server_create_secure_p12( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB, + _In_ LPCSTR szTlsClientCertPath, + _In_ LPCSTR szTlsServerP12Path, + _In_ LPCSTR szTlsServerP12Password +) { + // server certificate from .p12 file: + std::string sTlsClientCert; + std::string sTlsServerCert; + std::string sTlsServerCertPrivateKey; + if(!Util_LoadPemFromPkcs12(szTlsServerP12Path, szTlsServerP12Password, sTlsServerCertPrivateKey, sTlsServerCert)) { + std::cerr << "[Server] Failed to load mTLS server cert/key from .p12 file: " << szTlsServerP12Path << std::endl; + return NULL; + } + // client certificate: + if(!Util_LoadCaPemFromFile(szTlsClientCertPath, sTlsClientCert)) { + std::cerr << "[Server] Failed to load mTLS client ca cert from: " << szTlsClientCertPath << std::endl; + return NULL; + } + return leechgrpc_server_create_secure_internal(szAddress, dwPort, ctx, pfnReservedSubmitCommandCB, sTlsClientCert, sTlsServerCert, sTlsServerCertPrivateKey); +} + +/* +* Create a gRPC server with mTLS. +* -- szAddress: Address to listen on, e.g., "localhost" or " +* -- dwPort: Port to listen on. +* -- ctx: Optional context to pass to the callback function. +* -- pfnReservedSubmitCommandCB: Callback function to handle incoming commands. +* -- szTlsClientCertPath: Client CA certificate to trust for mTLS connections. +* -- szTlsServerCertPath: Server TLS certificate (incl. chain). +* -- szTlsServerCertPrivateKeyPath: Server TLS certificate private key. +* -- return: Handle to the gRPC server, or NULL on failure. +*/ +LEECHGRPC_EXPORTED_FUNCTION _Success_(return != NULL) +LEECHGRPC_SERVER_HANDLE leechgrpc_server_create_secure_pemfile( + _In_ LPCSTR szAddress, + _In_ DWORD dwPort, + _In_opt_ PVOID ctx, + _In_ PFN_RESERVED_SUBMIT_COMMAND_CB pfnReservedSubmitCommandCB, + _In_ LPCSTR szTlsClientCertPath, + _In_ LPCSTR szTlsServerCertPath, + _In_ LPCSTR szTlsServerCertPrivateKeyPath +) { + // Load the server's private key and certificate from the .p12 file + std::string sTlsClientCert; + std::string sTlsServerCert; + std::string sTlsServerCertPrivateKey; + if(!Util_LoadCaPemFromFile(szTlsServerCertPath, sTlsServerCert)) { + std::cerr << "[Server] Failed to load server ca certificate from: " << szTlsServerCertPath << std::endl; + return NULL; + } + if(!Util_LoadCaPemFromFile(szTlsServerCertPrivateKeyPath, sTlsServerCertPrivateKey)) { + std::cerr << "[Server] Failed to load server ca certificate private key from: " << szTlsServerCertPrivateKeyPath << std::endl; + return NULL; + } + if(!Util_LoadCaPemFromFile(szTlsClientCertPath, sTlsClientCert)) { + std::cerr << "[Server] Failed to load client ca certificate from: " << szTlsClientCertPath << std::endl; + return NULL; + } + return leechgrpc_server_create_secure_internal(szAddress, dwPort, ctx, pfnReservedSubmitCommandCB, sTlsClientCert, sTlsServerCert, sTlsServerCertPrivateKey); +} + +/* +* Wait for the gRPC server to shutdown. +* -- hGRPC: Handle to the gRPC server. +*/ +LEECHGRPC_EXPORTED_FUNCTION +VOID leechgrpc_server_wait(_In_ LEECHGRPC_SERVER_HANDLE hGRPC) +{ + auto pServer = reinterpret_cast*>(hGRPC); + (*pServer)->Wait(); +} + +/* +* Shut down the gRPC server. +* -- hGRPC: Handle to the gRPC server. +*/ +LEECHGRPC_EXPORTED_FUNCTION +VOID leechgrpc_server_shutdown(_In_ LEECHGRPC_SERVER_HANDLE hGRPC) +{ + auto pServer = reinterpret_cast*>(hGRPC); + (*pServer)->Shutdown(); + delete pServer; +} diff --git a/libleechgrpc/libleechgrpc.vcxproj b/libleechgrpc/libleechgrpc.vcxproj new file mode 100644 index 0000000..4614ee7 --- /dev/null +++ b/libleechgrpc/libleechgrpc.vcxproj @@ -0,0 +1,184 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {7f9de005-851f-4817-8749-0396da30b3f8} + leechgrpc + 10.0 + libleechgrpc + + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + Speed + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + Speed + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + Speed + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + Speed + true + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libleechgrpc/libleechgrpc.vcxproj.filters b/libleechgrpc/libleechgrpc.vcxproj.filters new file mode 100644 index 0000000..57e5f01 --- /dev/null +++ b/libleechgrpc/libleechgrpc.vcxproj.filters @@ -0,0 +1,68 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {e08fb88d-9d45-4866-9ec6-273e6ce4b653} + + + {4d4ccebb-a242-4d03-b043-48e5d6d6fa10} + + + {8cba3da9-b9ff-4e09-9e61-13629ff93cb0} + + + + + proto + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files\generated + + + Header Files\generated + + + + + Source Files\generated + + + Source Files\generated + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/libleechgrpc/libleechgrpc.vcxproj.user b/libleechgrpc/libleechgrpc.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/libleechgrpc/libleechgrpc.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/libleechgrpc/oscompatibility.cc b/libleechgrpc/oscompatibility.cc new file mode 100644 index 0000000..d81b5c3 --- /dev/null +++ b/libleechgrpc/oscompatibility.cc @@ -0,0 +1,29 @@ +// oscompatibility.c : LeechCore Windows/Linux compatibility layer. +// +// (c) Ulf Frisk, 2017-2025 +// Author: Ulf Frisk, pcileech@frizk.net +// + +#if defined(LINUX) || defined(MACOS) + +#include "oscompatibility.h" + +// ---------------------------------------------------------------------------- +// LocalAlloc/LocalFree BELOW: +// ---------------------------------------------------------------------------- + +HANDLE LocalAlloc(DWORD uFlags, SIZE_T uBytes) +{ + HANDLE h = malloc(uBytes); + if(h && (uFlags & LMEM_ZEROINIT)) { + memset(h, 0, uBytes); + } + return h; +} + +VOID LocalFree(HANDLE hMem) +{ + free(hMem); +} + +#endif /* LINUX || MACOS */ diff --git a/libleechgrpc/oscompatibility.h b/libleechgrpc/oscompatibility.h new file mode 100644 index 0000000..ba91f82 --- /dev/null +++ b/libleechgrpc/oscompatibility.h @@ -0,0 +1,160 @@ +// oscompatibility.h : LeechCore Windows/Linux compatibility layer. +// +// (c) Ulf Frisk, 2017-2025 +// Author: Ulf Frisk, pcileech@frizk.net +// +#ifndef __OSCOMPATIBILITY_H__ +#define __OSCOMPATIBILITY_H__ +#include "leechgrpc.h" + +#ifdef _WIN32 + +#include +#include + +#endif /* _WIN32 */ + +#if defined(LINUX) || defined(MACOS) +#define _FILE_OFFSET_BITS 64 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef void VOID, *PVOID; +typedef void *HANDLE, **PHANDLE, *HMODULE, *FARPROC; +typedef uint32_t BOOL, *PBOOL; +typedef uint8_t BYTE, *PBYTE; +typedef uint8_t UCHAR, *PUCHAR; +typedef char CHAR, *PCHAR, *PSTR, *LPSTR; +typedef const char *LPCSTR; +typedef int32_t LONG; +typedef uint16_t WORD, *PWORD, USHORT, *PUSHORT; +typedef uint16_t WCHAR, *PWCHAR, *LPWSTR; +typedef const uint16_t *LPCWSTR; +typedef uint32_t UINT, DWORD, *PDWORD, ULONG, *PULONG; +typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64; +typedef uint64_t LARGE_INTEGER, *PLARGE_INTEGER, FILETIME; +typedef size_t SIZE_T, *PSIZE_T; +typedef void *OVERLAPPED, *LPOVERLAPPED; +typedef struct tdEXCEPTION_RECORD32 { CHAR sz[80]; } EXCEPTION_RECORD32; +typedef struct tdEXCEPTION_RECORD64 { CHAR sz[152]; } EXCEPTION_RECORD64; +typedef int(*_CoreCrtNonSecureSearchSortCompareFunction)(void const *, void const *); +#define __forceinline inline __attribute__((always_inline)) +#define TRUE 1 +#define FALSE 0 +#define MAX_PATH 260 +#define LMEM_ZEROINIT 0x0040 +#define INVALID_HANDLE_VALUE ((HANDLE)-1) +#define STD_INPUT_HANDLE ((DWORD)-10) +#define STD_OUTPUT_HANDLE ((DWORD)-11) +#define GENERIC_WRITE (0x40000000L) +#define GENERIC_READ (0x80000000L) +#define FILE_SHARE_READ (0x00000001L) +#define CREATE_NEW (0x00000001L) +#define OPEN_EXISTING (0x00000003L) +#define FILE_ATTRIBUTE_NORMAL (0x00000080L) +#define STILL_ACTIVE (0x00000103L) +#define CRYPT_STRING_HEX_ANY (0x00000008L) +#define CRYPT_STRING_HEXASCIIADDR (0x00000008L) +#define STILL_ACTIVE (0x00000103L) +#define INVALID_FILE_SIZE (0xffffffffL) +#define _TRUNCATE ((SIZE_T)-1LL) +#define LPTHREAD_START_ROUTINE PVOID +#define WINUSB_INTERFACE_HANDLE libusb_device_handle* +#define PIPE_TRANSFER_TIMEOUT 0x03 +#define CONSOLE_SCREEN_BUFFER_INFO PVOID // TODO: remove this dummy +#define SOCKET int +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#define WSAEWOULDBLOCK 10035L +#define MAXIMUM_WAIT_OBJECTS 64 +#define WAIT_OBJECT_0 (0x00000000UL) +#define WAIT_FAILED (0xFFFFFFFFUL) +#define WAIT_TIMEOUT (258L) +#define INFINITE (0xFFFFFFFFUL) +#define E_FAIL (0x80004005UL) +#define error_status_t DWORD +#define SecureZeroMemory(pb, cb) (ZeroMemory(pb, cb)) +#define _itoa_s(n, s, l, b) (snprintf(s, l, "%d", n)) + +#define _In_ +#define _In_z_ +#define _Out_ +#define _Inout_ +#define _Inout_opt_ +#define _In_opt_ +#define _In_opt_z_ +#define _Out_opt_ +#define _Check_return_opt_ +#define _Frees_ptr_opt_ +#define _Post_ptr_invalid_ +#define _Printf_format_string_ +#define _In_reads_(x) +#define _In_reads_opt_(x) +#define _Out_writes_(x) +#define __bcount(x) +#define _Inout_bytecount_(x) +#define _Inout_updates_opt_(x) +#define _Inout_updates_bytes_(x) +#define _Out_writes_opt_(x) +#define _Success_(x) +#define UNREFERENCED_PARAMETER(x) +#define WINAPI + +#define _byteswap_ushort(v) (__builtin_bswap16(v)) +#define _byteswap_ulong(v) (__builtin_bswap32(v)) +#define _byteswap_uint64(v) (__builtin_bswap64(v)) +#ifndef _rotr +#define _rotr(v,c) ((((DWORD)v) >> ((DWORD)c) | (DWORD)((DWORD)v) << (32 - (DWORD)c))) +#endif /* _rotr */ +#define _rotr16(v,c) ((((WORD)v) >> ((WORD)c) | (WORD)((WORD)v) << (16 - (WORD)c))) +#define _rotr64(v,c) ((((QWORD)v) >> ((QWORD)c) | (QWORD)((QWORD)v) << (64 - (QWORD)c))) +#define _rotl64(v,c) ((QWORD)(((QWORD)v) << ((QWORD)c)) | (((QWORD)v) >> (64 - (QWORD)c))) +#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) +#define sprintf_s(s, maxcount, ...) (snprintf(s, maxcount, __VA_ARGS__)) +#define strnlen_s(s, maxcount) (strnlen(s, maxcount)) +#define strcpy_s(dst, len, src) (strncpy(dst, src, len)) +#define strncpy_s(dst, len, src, srclen) (strncpy(dst, src, min((QWORD)(max(1, len)) - 1, (QWORD)(srclen)))) +#define strncat_s(dst, dstlen, src, srclen) (strncat(dst, src, min((((strlen(dst) + 1 >= (QWORD)(dstlen)) || ((QWORD)(dstlen) == 0)) ? 0 : ((QWORD)(dstlen) - strlen(dst) - 1)), (QWORD)(srclen)))) +#define strcat_s(dst, dstlen, src) (strncat_s(dst, dstlen, src, _TRUNCATE)) +#define _vsnprintf_s(dst, len, cnt, fmt, a) (vsnprintf(dst, min((QWORD)(len), (QWORD)(cnt)), fmt, a)) +#define _stricmp(s1, s2) (strcasecmp(s1, s2)) +#define _strnicmp(s1, s2, maxcount) (strncasecmp(s1, s2, maxcount)) +#define strtok_s(s, d, c) (strtok_r(s, d, c)) +#define _snprintf_s(s,l,c,...) (snprintf(s,l,__VA_ARGS__)) +#define sscanf_s(s, f, ...) (sscanf(s, f, __VA_ARGS__)) +#define SwitchToThread() (sched_yield()) +#define ExitThread(dwExitCode) (pthread_exit(dwExitCode)) +#define ExitProcess(c) (exit(c ? EXIT_SUCCESS : EXIT_FAILURE)) +#define Sleep(dwMilliseconds) (usleep(1000*dwMilliseconds)) +#define fopen_s(ppFile, szFile, szAttr) ((*ppFile = fopen(szFile, szAttr)) ? 0 : 1) +#define GetModuleFileNameA(m, f, l) (readlink("/proc/self/exe", f, l)) +#define ZeroMemory(pb, cb) (memset(pb, 0, cb)) +#define WinUsb_SetPipePolicy(h, p, t, cb, pb) // TODO: implement this for better USB2 performance. +#define WSAGetLastError() (WSAEWOULDBLOCK) // TODO: remove this dummy when possible. +#define _ftelli64(f) (ftello(f)) +#define _fseeki64(f, o, w) (fseeko(f, o, w)) +#define _chsize_s(fd, cb) (ftruncate64(fd, cb)) +#define _fileno(f) (fileno(f)) +#define InterlockedAdd64(p, v) (__sync_add_and_fetch_8(p, v)) +#define InterlockedIncrement64(p) (__sync_add_and_fetch_8(p, 1)) +#define InterlockedIncrement(p) (__sync_add_and_fetch_4(p, 1)) +#define InterlockedDecrement(p) (__sync_sub_and_fetch_4(p, 1)) +#define GetCurrentProcess() ((HANDLE)-1) +#define closesocket(s) close(s) + +HANDLE LocalAlloc(DWORD uFlags, SIZE_T uBytes); +VOID LocalFree(HANDLE hMem); + +#endif /* LINUX || MACOS */ + +#endif /* __OSCOMPATIBILITY_H__ */ diff --git a/libleechgrpc/proto/leechgrpc.proto b/libleechgrpc/proto/leechgrpc.proto new file mode 100644 index 0000000..b596b02 --- /dev/null +++ b/libleechgrpc/proto/leechgrpc.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +package leechrpc; + +service LeechRpc { + // Mirrors the MSRPC call: LeechRpc_ReservedSubmitCommand + rpc ReservedSubmitCommand(SubmitCommandRequest) returns (SubmitCommandResponse); +} + +message SubmitCommandRequest { + bytes pbIn = 1; +} + +message SubmitCommandResponse { + bytes pbOut = 1; +} diff --git a/libleechgrpc/util.cc b/libleechgrpc/util.cc new file mode 100644 index 0000000..d4a13b1 --- /dev/null +++ b/libleechgrpc/util.cc @@ -0,0 +1,126 @@ +#include "leechgrpc.h" +#include "oscompatibility.h" +#include "util.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +_Success_(return) +bool Util_LoadPemFromPkcs12( + _In_ const std::string &pkcs12Path, + _In_ const std::string &password, + _Out_ std::string &outPrivateKeyPem, + _Out_ std::string &outCertPem +) { + // Open PKCS#12 file: + FILE *fp = NULL; + if(fopen_s(&fp, pkcs12Path.c_str(), "rb")) { + fprintf(stderr, "Failed to open P12 file: %s\n", pkcs12Path.c_str()); + return false; + } + // Read the file into a PKCS12 structure + PKCS12 *p12 = d2i_PKCS12_fp(fp, nullptr); + fclose(fp); + if(!p12) { + fprintf(stderr, "Failed to d2i_PKCS12_fp\n"); + return false; + } + // Parse the PKCS12 + EVP_PKEY *pkey = nullptr; + X509 *cert = nullptr; + STACK_OF(X509) *ca = nullptr; + if(!PKCS12_parse(p12, password.c_str(), &pkey, &cert, &ca)) { + fprintf(stderr, "Failed to parse PKCS12\n"); + PKCS12_free(p12); + return false; + } + PKCS12_free(p12); + // Convert private key to PEM + { + BIO *bio = BIO_new(BIO_s_mem()); + if(!PEM_write_bio_PrivateKey(bio, pkey, nullptr, nullptr, 0, nullptr, nullptr)) { + fprintf(stderr, "Failed to write private key to PEM\n"); + EVP_PKEY_free(pkey); + X509_free(cert); + //sk_X509_pop_free(ca, X509_free); + BIO_free(bio); + return false; + } + // Read the PEM data from the BIO into outPrivateKeyPem + char *pemData = nullptr; + long pemLen = BIO_get_mem_data(bio, &pemData); + outPrivateKeyPem.assign(pemData, pemLen); + BIO_free(bio); + } + // Convert cert (and optional chain) to PEM + { + BIO *bio = BIO_new(BIO_s_mem()); + // Write the main certificate + if(!PEM_write_bio_X509(bio, cert)) { + fprintf(stderr, "Failed to write certificate to PEM\n"); + EVP_PKEY_free(pkey); + X509_free(cert); + //sk_X509_pop_free(ca, X509_free); + BIO_free(bio); + return false; + } + // Optionally write out the chain certs + if(ca) { + int count = sk_X509_num(ca); + for(int i = 0; i < count; i++) { + X509 *chainCert = sk_X509_value(ca, i); + PEM_write_bio_X509(bio, chainCert); + } + } + char *pemData = nullptr; + long pemLen = BIO_get_mem_data(bio, &pemData); + outCertPem.assign(pemData, pemLen); + BIO_free(bio); + } + // Cleanup + EVP_PKEY_free(pkey); + X509_free(cert); + //if(ca) { + // sk_X509_pop_free(ca, X509_free); + //} + return true; + //return false; +} + +_Success_(return) +bool Util_LoadCaPemFromFile( + _In_ const std::string &filePath, + _Out_ std::string &outCertPem +) { + // Clear the output parameter just in case + outCertPem.clear(); + // Open the file in binary mode + std::ifstream file(filePath, std::ios::in | std::ios::binary); + if(!file.is_open()) { + std::cerr << "[Util_LoadCaPemFromFile] Failed to open CA certificate file: " + << filePath << std::endl; + return false; + } + // Read entire file into a temporary string + std::string pem( + (std::istreambuf_iterator(file)), + std::istreambuf_iterator() + ); + file.close(); + // Basic validation: Check if the file content is not empty + if(pem.empty()) { + std::cerr << "[Util_LoadCaPemFromFile] CA certificate file is empty: " + << filePath << std::endl; + return false; + } + // Assign to output parameter + outCertPem = std::move(pem); + return true; +} diff --git a/libleechgrpc/util.h b/libleechgrpc/util.h new file mode 100644 index 0000000..b59f979 --- /dev/null +++ b/libleechgrpc/util.h @@ -0,0 +1,23 @@ +#ifndef __UTIL_H__ +#define __UTIL_H__ + +#include "leechgrpc.h" +#include +#include +#include + +_Success_(return) +bool Util_LoadPemFromPkcs12( + _In_ const std::string &pkcs12Path, + _In_ const std::string &password, + _Out_ std::string &outPrivateKeyPem, + _Out_ std::string &outCertPem +); + +_Success_(return) +bool Util_LoadCaPemFromFile( + _In_ const std::string &filePath, + _Out_ std::string &outCertPem +); + +#endif /* __UTIL_H__ */