commit 58d550dc2e2437bc8e87f43c16112d7a9bcee9f1 Author: openKylinBot Date: Mon May 16 16:01:04 2022 +0800 Import Upstream version 5.92.0 diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..a6557de --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,5 @@ +#clang-format/tidy +691c88fc043d0869f45b2599dd50f0d24fe354bf +4f93a935a58cd83eb16da36b2230509d98a272b3 +92eab58db2b4bb520387ef6e7610753f798d314c +c70f6b8ddb8a5136f1686179c3a0cbf7c8fa1134 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d84c817 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# Ignore the following files +*~ +*.[oa] +*.diff +*.kate-swp +*.kdev4 +.kdev_include_paths +*.kdevelop.pcs +*.moc +*.moc.cpp +*.orig +*.user +.*.swp +.swp.* +Doxyfile +Makefile +avail +random_seed +/build*/ +CMakeLists.txt.user* +*.unc-backup* +.cmake/ +/.clang-format +/compile_commands.json +.clangd +.idea +/cmake-build* +.cache diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..d2a9f84 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2020 Volker Krause +# SPDX-License-Identifier: CC0-1.0 + +include: + - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml + - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml + - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml diff --git a/.kde-ci.yml b/.kde-ci.yml new file mode 100644 index 0000000..aadc699 --- /dev/null +++ b/.kde-ci.yml @@ -0,0 +1,10 @@ +Dependencies: +- 'on': ['Linux', 'FreeBSD'] + 'require': + 'frameworks/extra-cmake-modules': '@same' + 'frameworks/kconfig' : '@same' + 'frameworks/kcoreaddons' : '@same' + 'frameworks/kpty' : '@same' + +Options: + test-before-installing: True diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0663a81 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.16) + +set(KF_VERSION "5.92.0") # handled by release scripts +set(KF_DEP_VERSION "5.92.0") # handled by release scripts +project(KDESu VERSION ${KF_VERSION}) + +include(FeatureSummary) +find_package(ECM 5.92.0 NO_MODULE) +set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules") +feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) + + +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) + +set(REQUIRED_QT_VERSION 5.15.2) +include(KDEInstallDirs) +find_package(Qt${QT_MAJOR_VERSION}Core ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE) +include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) +include(KDECMakeSettings) + +find_package(KF5Config ${KF_DEP_VERSION} REQUIRED) +find_package(KF5CoreAddons ${KF_DEP_VERSION} REQUIRED) +find_package(KF5I18n ${KF_DEP_VERSION} REQUIRED) +find_package(KF5Pty ${KF_DEP_VERSION} REQUIRED) + +#optional features +find_package(X11) +set(HAVE_X11 ${X11_FOUND}) + + +include(ECMGenerateExportHeader) +include(ECMSetupVersion) +include(ECMGenerateHeaders) +include(ECMMarkNonGuiExecutable) +include(ECMQtDeclareLoggingCategory) +include(ECMAddQch) + +set(EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 CACHE STRING "Control the range of deprecated API excluded from the build [default=0].") + +option(KDESU_USE_SUDO_DEFAULT "Set On to use sudo instead of su [default=Off]" Off) +option(KDESU_USE_DOAS_DEFAULT "Set On to use doas instead of su and sudo [default=Off]" Off) +if(KDESU_USE_SUDO_DEFAULT AND KDESU_USE_DOAS_DEFAULT) + message(FATAL_ERROR "Choose between sudo(1) or doas(1)") +elseif(KDESU_USE_SUDO_DEFAULT) + message("Using sudo as default") +elseif(KDESU_USE_DOAS_DEFAULT) + message("Using doas as default") +else() + message("Using su as default (set KDESU_USE_SUDO_DEFAULT=On to use sudo)") +endif() + +option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)" OFF) +add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)") + +ecm_setup_version(PROJECT VARIABLE_PREFIX KDESU + VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kdesu_version.h" + PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5SuConfigVersion.cmake" + SOVERSION 5) +add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050f02) +add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x055100) +ki18n_install(po) +add_subdirectory(src) + +# create a Config.cmake and a ConfigVersion.cmake file and install them +set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5Su") + +if (BUILD_QCH) + ecm_install_qch_export( + TARGETS KF5Su_QCH + FILE KF5SuQchTargets.cmake + DESTINATION "${CMAKECONFIG_INSTALL_DIR}" + COMPONENT Devel + ) + set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KF5SuQchTargets.cmake\")") +endif() + +include(CMakePackageConfigHelpers) + +configure_package_config_file( + "${CMAKE_CURRENT_SOURCE_DIR}/KF5SuConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/KF5SuConfig.cmake" + INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} +) + +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/KF5SuConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/KF5SuConfigVersion.cmake" + DESTINATION "${CMAKECONFIG_INSTALL_DIR}" + COMPONENT Devel +) + +install(EXPORT KF5SuTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5SuTargets.cmake NAMESPACE KF5:: ) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/kdesu_version.h + DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KDESu COMPONENT Devel +) + +if(BUILD_TESTING) + add_subdirectory(autotests) +endif() + +feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/KF5SuConfig.cmake.in b/KF5SuConfig.cmake.in new file mode 100644 index 0000000..e8a998a --- /dev/null +++ b/KF5SuConfig.cmake.in @@ -0,0 +1,7 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) +find_dependency(KF5Pty "@KF_DEP_VERSION@") + +include("${CMAKE_CURRENT_LIST_DIR}/KF5SuTargets.cmake") +@PACKAGE_INCLUDE_QCHTARGETS@ diff --git a/LICENSES/CC0-1.0.txt b/LICENSES/CC0-1.0.txt new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/LICENSES/CC0-1.0.txt @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/LICENSES/GPL-2.0-only.txt b/LICENSES/GPL-2.0-only.txt new file mode 100644 index 0000000..0f3d641 --- /dev/null +++ b/LICENSES/GPL-2.0-only.txt @@ -0,0 +1,319 @@ +GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. + +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to +most of the Free Software Foundation's software and to any other program whose +authors commit to using it. (Some other Free Software Foundation software +is covered by the GNU Lesser General Public License instead.) You can apply +it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom +to distribute copies of free software (and charge for this service if you +wish), that you receive source code or can get it if you want it, that you +can change the software or use pieces of it in new free programs; and that +you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to +deny you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of +the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or +for a fee, you must give the recipients all the rights that you have. You +must make sure that they, too, receive or can get the source code. And you +must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) +offer you this license which gives you legal permission to copy, distribute +and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If +the software is modified by someone else and passed on, we want its recipients +to know that what they have is not the original, so that any problems introduced +by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We +wish to avoid the danger that redistributors of a free program will individually +obtain patent licenses, in effect making the program proprietary. To prevent +this, we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms +of this General Public License. The "Program", below, refers to any such program +or work, and a "work based on the Program" means either the Program or any +derivative work under copyright law: that is to say, a work containing the +Program or a portion of it, either verbatim or with modifications and/or translated +into another language. (Hereinafter, translation is included without limitation +in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered +by this License; they are outside its scope. The act of running the Program +is not restricted, and the output from the Program is covered only if its +contents constitute a work based on the Program (independent of having been +made by running the Program). Whether that is true depends on what the Program +does. + +1. You may copy and distribute verbatim copies of the Program's source code +as you receive it, in any medium, provided that you conspicuously and appropriately +publish on each copy an appropriate copyright notice and disclaimer of warranty; +keep intact all the notices that refer to this License and to the absence +of any warranty; and give any other recipients of the Program a copy of this +License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you +may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, +thus forming a work based on the Program, and copy and distribute such modifications +or work under the terms of Section 1 above, provided that you also meet all +of these conditions: + +a) You must cause the modified files to carry prominent notices stating that +you changed the files and the date of any change. + +b) You must cause any work that you distribute or publish, that in whole or +in part contains or is derived from the Program or any part thereof, to be +licensed as a whole at no charge to all third parties under the terms of this +License. + +c) If the modified program normally reads commands interactively when run, +you must cause it, when started running for such interactive use in the most +ordinary way, to print or display an announcement including an appropriate +copyright notice and a notice that there is no warranty (or else, saying that +you provide a warranty) and that users may redistribute the program under +these conditions, and telling the user how to view a copy of this License. +(Exception: if the Program itself is interactive but does not normally print +such an announcement, your work based on the Program is not required to print +an announcement.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, and can be reasonably +considered independent and separate works in themselves, then this License, +and its terms, do not apply to those sections when you distribute them as +separate works. But when you distribute the same sections as part of a whole +which is a work based on the Program, the distribution of the whole must be +on the terms of this License, whose permissions for other licensees extend +to the entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise +the right to control the distribution of derivative or collective works based +on the Program. + +In addition, mere aggregation of another work not based on the Program with +the Program (or with a work based on the Program) on a volume of a storage +or distribution medium does not bring the other work under the scope of this +License. + +3. You may copy and distribute the Program (or a work based on it, under Section +2) in object code or executable form under the terms of Sections 1 and 2 above +provided that you also do one of the following: + +a) Accompany it with the complete corresponding machine-readable source code, +which must be distributed under the terms of Sections 1 and 2 above on a medium +customarily used for software interchange; or, + +b) Accompany it with a written offer, valid for at least three years, to give +any third party, for a charge no more than your cost of physically performing +source distribution, a complete machine-readable copy of the corresponding +source code, to be distributed under the terms of Sections 1 and 2 above on +a medium customarily used for software interchange; or, + +c) Accompany it with the information you received as to the offer to distribute +corresponding source code. (This alternative is allowed only for noncommercial +distribution and only if you received the program in object code or executable +form with such an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for making +modifications to it. For an executable work, complete source code means all +the source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and installation +of the executable. However, as a special exception, the source code distributed +need not include anything that is normally distributed (in either source or +binary form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component itself +accompanies the executable. + +If distribution of executable or object code is made by offering access to +copy from a designated place, then offering equivalent access to copy the +source code from the same place counts as distribution of the source code, +even though third parties are not compelled to copy the source along with +the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except +as expressly provided under this License. Any attempt otherwise to copy, modify, +sublicense or distribute the Program is void, and will automatically terminate +your rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses terminated +so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed +it. However, nothing else grants you permission to modify or distribute the +Program or its derivative works. These actions are prohibited by law if you +do not accept this License. Therefore, by modifying or distributing the Program +(or any work based on the Program), you indicate your acceptance of this License +to do so, and all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), +the recipient automatically receives a license from the original licensor +to copy, distribute or modify the Program subject to these terms and conditions. +You may not impose any further restrictions on the recipients' exercise of +the rights granted herein. You are not responsible for enforcing compliance +by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement +or for any other reason (not limited to patent issues), conditions are imposed +on you (whether by court order, agreement or otherwise) that contradict the +conditions of this License, they do not excuse you from the conditions of +this License. If you cannot distribute so as to satisfy simultaneously your +obligations under this License and any other pertinent obligations, then as +a consequence you may not distribute the Program at all. For example, if a +patent license would not permit royalty-free redistribution of the Program +by all those who receive copies directly or indirectly through you, then the +only way you could satisfy both it and this License would be to refrain entirely +from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply and +the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents +or other property right claims or to contest validity of any such claims; +this section has the sole purpose of protecting the integrity of the free +software distribution system, which is implemented by public license practices. +Many people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose +that choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original copyright +holder who places the Program under this License may add an explicit geographical +distribution limitation excluding those countries, so that distribution is +permitted only in or among countries not thus excluded. In such case, this +License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of +the General Public License from time to time. Such new versions will be similar +in spirit to the present version, but may differ in detail to address new +problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies +a version number of this License which applies to it and "any later version", +you have the option of following the terms and conditions either of that version +or of any later version published by the Free Software Foundation. If the +Program does not specify a version number of this License, you may choose +any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, write to the author to ask for +permission. For software which is copyrighted by the Free Software Foundation, +write to the Free Software Foundation; we sometimes make exceptions for this. +Our decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing and reuse +of software generally. + + NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM +"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE +OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE +OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA +OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES +OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH +HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively convey the exclusion +of warranty; and each file should have at least the "copyright" line and a +pointer to where the full notice is found. + + + +Copyright (C)< yyyy> + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 51 Franklin +Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when +it starts in an interactive mode: + +Gnomovision version 69, Copyright (C) year name of author Gnomovision comes +with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, +and you are welcome to redistribute it under certain conditions; type `show +c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may be +called something other than `show w' and `show c'; they could even be mouse-clicks +or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the program, if necessary. Here +is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' +(which makes passes at compilers) written by James Hacker. + +, 1 April 1989 Ty Coon, President of Vice This General +Public License does not permit incorporating your program into proprietary +programs. If your program is a subroutine library, you may consider it more +useful to permit linking proprietary applications with the library. If this +is what you want to do, use the GNU Lesser General Public License instead +of this License. diff --git a/LICENSES/LGPL-2.0-or-later.txt b/LICENSES/LGPL-2.0-or-later.txt new file mode 100644 index 0000000..5c96471 --- /dev/null +++ b/LICENSES/LGPL-2.0-or-later.txt @@ -0,0 +1,446 @@ +GNU LIBRARY GENERAL PUBLIC LICENSE + +Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. + +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is numbered 2 because +it goes with version 2 of the ordinary GPL.] + +Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public Licenses are intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. + +This license, the Library General Public License, applies to some specially +designated Free Software Foundation software, and to any other libraries whose +authors decide to use it. You can use it for your libraries, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom +to distribute copies of free software (and charge for this service if you +wish), that you receive source code or can get it if you want it, that you +can change the software or use pieces of it in new free programs; and that +you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to +deny you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of +the library, or if you modify it. + +For example, if you distribute copies of the library, whether gratis or for +a fee, you must give the recipients all the rights that we gave you. You must +make sure that they, too, receive or can get the source code. If you link +a program with the library, you must provide complete object files to the +recipients so that they can relink them with the library, after making changes +to the library and recompiling it. And you must show them these terms so they +know their rights. + +Our method of protecting your rights has two steps: (1) copyright the library, +and (2) offer you this license which gives you legal permission to copy, distribute +and/or modify the library. + +Also, for each distributor's protection, we want to make certain that everyone +understands that there is no warranty for this free library. If the library +is modified by someone else and passed on, we want its recipients to know +that what they have is not the original version, so that any problems introduced +by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We +wish to avoid the danger that companies distributing free software will individually +obtain patent licenses, thus in effect transforming the program into proprietary +software. To prevent this, we have made it clear that any patent must be licensed +for everyone's free use or not licensed at all. + +Most GNU software, including some libraries, is covered by the ordinary GNU +General Public License, which was designed for utility programs. This license, +the GNU Library General Public License, applies to certain designated libraries. +This license is quite different from the ordinary one; be sure to read it +in full, and don't assume that anything in it is the same as in the ordinary +license. + +The reason we have a separate public license for some libraries is that they +blur the distinction we usually make between modifying or adding to a program +and simply using it. Linking a program with a library, without changing the +library, is in some sense simply using the library, and is analogous to running +a utility program or application program. However, in a textual and legal +sense, the linked executable is a combined work, a derivative of the original +library, and the ordinary General Public License treats it as such. + +Because of this blurred distinction, using the ordinary General Public License +for libraries did not effectively promote software sharing, because most developers +did not use the libraries. We concluded that weaker conditions might promote +sharing better. + +However, unrestricted linking of non-free programs would deprive the users +of those programs of all benefit from the free status of the libraries themselves. +This Library General Public License is intended to permit developers of non-free +programs to use free libraries, while preserving your freedom as a user of +such programs to change the free libraries that are incorporated in them. +(We have not seen how to achieve this as regards changes in header files, +but we have achieved it as regards changes in the actual functions of the +Library.) The hope is that this will lead to faster development of free libraries. + +The precise terms and conditions for copying, distribution and modification +follow. Pay close attention to the difference between a "work based on the +library" and a "work that uses the library". The former contains code derived +from the library, while the latter only works together with the library. + +Note that it is possible for a library to be covered by the ordinary General +Public License rather than by this special one. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License Agreement applies to any software library which contains a +notice placed by the copyright holder or other authorized party saying it +may be distributed under the terms of this Library General Public License +(also called "this License"). Each licensee is addressed as "you". + +A "library" means a collection of software functions and/or data prepared +so as to be conveniently linked with application programs (which use some +of those functions and data) to form executables. + +The "Library", below, refers to any such software library or work which has +been distributed under these terms. A "work based on the Library" means either +the Library or any derivative work under copyright law: that is to say, a +work containing the Library or a portion of it, either verbatim or with modifications +and/or translated straightforwardly into another language. (Hereinafter, translation +is included without limitation in the term "modification".) + +"Source code" for a work means the preferred form of the work for making modifications +to it. For a library, complete source code means all the source code for all +modules it contains, plus any associated interface definition files, plus +the scripts used to control compilation and installation of the library. + +Activities other than copying, distribution and modification are not covered +by this License; they are outside its scope. The act of running a program +using the Library is not restricted, and output from such a program is covered +only if its contents constitute a work based on the Library (independent of +the use of the Library in a tool for writing it). Whether that is true depends +on what the Library does and what the program that uses the Library does. + +1. You may copy and distribute verbatim copies of the Library's complete source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and disclaimer +of warranty; keep intact all the notices that refer to this License and to +the absence of any warranty; and distribute a copy of this License along with +the Library. + +You may charge a fee for the physical act of transferring a copy, and you +may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Library or any portion of it, +thus forming a work based on the Library, and copy and distribute such modifications +or work under the terms of Section 1 above, provided that you also meet all +of these conditions: + + a) The modified work must itself be a software library. + +b) You must cause the files modified to carry prominent notices stating that +you changed the files and the date of any change. + +c) You must cause the whole of the work to be licensed at no charge to all +third parties under the terms of this License. + +d) If a facility in the modified Library refers to a function or a table of +data to be supplied by an application program that uses the facility, other +than as an argument passed when the facility is invoked, then you must make +a good faith effort to ensure that, in the event an application does not supply +such function or table, the facility still operates, and performs whatever +part of its purpose remains meaningful. + +(For example, a function in a library to compute square roots has a purpose +that is entirely well-defined independent of the application. Therefore, Subsection +2d requires that any application-supplied function or table used by this function +must be optional: if the application does not supply it, the square root function +must still compute square roots.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Library, and can be reasonably +considered independent and separate works in themselves, then this License, +and its terms, do not apply to those sections when you distribute them as +separate works. But when you distribute the same sections as part of a whole +which is a work based on the Library, the distribution of the whole must be +on the terms of this License, whose permissions for other licensees extend +to the entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise +the right to control the distribution of derivative or collective works based +on the Library. + +In addition, mere aggregation of another work not based on the Library with +the Library (or with a work based on the Library) on a volume of a storage +or distribution medium does not bring the other work under the scope of this +License. + +3. You may opt to apply the terms of the ordinary GNU General Public License +instead of this License to a given copy of the Library. To do this, you must +alter all the notices that refer to this License, so that they refer to the +ordinary GNU General Public License, version 2, instead of to this License. +(If a newer version than version 2 of the ordinary GNU General Public License +has appeared, then you can specify that version instead if you wish.) Do not +make any other change in these notices. + +Once this change is made in a given copy, it is irreversible for that copy, +so the ordinary GNU General Public License applies to all subsequent copies +and derivative works made from that copy. + +This option is useful when you wish to copy part of the code of the Library +into a program that is not a library. + +4. You may copy and distribute the Library (or a portion or derivative of +it, under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you accompany it with the complete corresponding +machine-readable source code, which must be distributed under the terms of +Sections 1 and 2 above on a medium customarily used for software interchange. + +If distribution of object code is made by offering access to copy from a designated +place, then offering equivalent access to copy the source code from the same +place satisfies the requirement to distribute the source code, even though +third parties are not compelled to copy the source along with the object code. + +5. A program that contains no derivative of any portion of the Library, but +is designed to work with the Library by being compiled or linked with it, +is called a "work that uses the Library". Such a work, in isolation, is not +a derivative work of the Library, and therefore falls outside the scope of +this License. + +However, linking a "work that uses the Library" with the Library creates an +executable that is a derivative of the Library (because it contains portions +of the Library), rather than a "work that uses the library". The executable +is therefore covered by this License. Section 6 states terms for distribution +of such executables. + +When a "work that uses the Library" uses material from a header file that +is part of the Library, the object code for the work may be a derivative work +of the Library even though the source code is not. Whether this is true is +especially significant if the work can be linked without the Library, or if +the work is itself a library. The threshold for this to be true is not precisely +defined by law. + +If such an object file uses only numerical parameters, data structure layouts +and accessors, and small macros and small inline functions (ten lines or less +in length), then the use of the object file is unrestricted, regardless of +whether it is legally a derivative work. (Executables containing this object +code plus portions of the Library will still fall under Section 6.) + +Otherwise, if the work is a derivative of the Library, you may distribute +the object code for the work under the terms of Section 6. Any executables +containing that work also fall under Section 6, whether or not they are linked +directly with the Library itself. + +6. As an exception to the Sections above, you may also compile or link a "work +that uses the Library" with the Library to produce a work containing portions +of the Library, and distribute that work under terms of your choice, provided +that the terms permit modification of the work for the customer's own use +and reverse engineering for debugging such modifications. + +You must give prominent notice with each copy of the work that the Library +is used in it and that the Library and its use are covered by this License. +You must supply a copy of this License. If the work during execution displays +copyright notices, you must include the copyright notice for the Library among +them, as well as a reference directing the user to the copy of this License. +Also, you must do one of these things: + +a) Accompany the work with the complete corresponding machine-readable source +code for the Library including whatever changes were used in the work (which +must be distributed under Sections 1 and 2 above); and, if the work is an +executable linked with the Library, with the complete machine-readable "work +that uses the Library", as object code and/or source code, so that the user +can modify the Library and then relink to produce a modified executable containing +the modified Library. (It is understood that the user who changes the contents +of definitions files in the Library will not necessarily be able to recompile +the application to use the modified definitions.) + +b) Accompany the work with a written offer, valid for at least three years, +to give the same user the materials specified in Subsection 6a, above, for +a charge no more than the cost of performing this distribution. + +c) If distribution of the work is made by offering access to copy from a designated +place, offer equivalent access to copy the above specified materials from +the same place. + +d) Verify that the user has already received a copy of these materials or +that you have already sent this user a copy. + +For an executable, the required form of the "work that uses the Library" must +include any data and utility programs needed for reproducing the executable +from it. However, as a special exception, the source code distributed need +not include anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the operating +system on which the executable runs, unless that component itself accompanies +the executable. + +It may happen that this requirement contradicts the license restrictions of +other proprietary libraries that do not normally accompany the operating system. +Such a contradiction means you cannot use both them and the Library together +in an executable that you distribute. + +7. You may place library facilities that are a work based on the Library side-by-side +in a single library together with other library facilities not covered by +this License, and distribute such a combined library, provided that the separate +distribution of the work based on the Library and of the other library facilities +is otherwise permitted, and provided that you do these two things: + +a) Accompany the combined library with a copy of the same work based on the +Library, uncombined with any other library facilities. This must be distributed +under the terms of the Sections above. + +b) Give prominent notice with the combined library of the fact that part of +it is a work based on the Library, and explaining where to find the accompanying +uncombined form of the same work. + +8. You may not copy, modify, sublicense, link with, or distribute the Library +except as expressly provided under this License. Any attempt otherwise to +copy, modify, sublicense, link with, or distribute the Library is void, and +will automatically terminate your rights under this License. However, parties +who have received copies, or rights, from you under this License will not +have their licenses terminated so long as such parties remain in full compliance. + +9. You are not required to accept this License, since you have not signed +it. However, nothing else grants you permission to modify or distribute the +Library or its derivative works. These actions are prohibited by law if you +do not accept this License. Therefore, by modifying or distributing the Library +(or any work based on the Library), you indicate your acceptance of this License +to do so, and all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + +10. Each time you redistribute the Library (or any work based on the Library), +the recipient automatically receives a license from the original licensor +to copy, distribute, link with or modify the Library subject to these terms +and conditions. You may not impose any further restrictions on the recipients' +exercise of the rights granted herein. You are not responsible for enforcing +compliance by third parties to this License. + +11. If, as a consequence of a court judgment or allegation of patent infringement +or for any other reason (not limited to patent issues), conditions are imposed +on you (whether by court order, agreement or otherwise) that contradict the +conditions of this License, they do not excuse you from the conditions of +this License. If you cannot distribute so as to satisfy simultaneously your +obligations under this License and any other pertinent obligations, then as +a consequence you may not distribute the Library at all. For example, if a +patent license would not permit royalty-free redistribution of the Library +by all those who receive copies directly or indirectly through you, then the +only way you could satisfy both it and this License would be to refrain entirely +from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents +or other property right claims or to contest validity of any such claims; +this section has the sole purpose of protecting the integrity of the free +software distribution system which is implemented by public license practices. +Many people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose +that choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +12. If the distribution and/or use of the Library is restricted in certain +countries either by patents or by copyrighted interfaces, the original copyright +holder who places the Library under this License may add an explicit geographical +distribution limitation excluding those countries, so that distribution is +permitted only in or among countries not thus excluded. In such case, this +License incorporates the limitation as if written in the body of this License. + +13. The Free Software Foundation may publish revised and/or new versions of +the Library General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to address +new problems or concerns. + +Each version is given a distinguishing version number. If the Library specifies +a version number of this License which applies to it and "any later version", +you have the option of following the terms and conditions either of that version +or of any later version published by the Free Software Foundation. If the +Library does not specify a license version number, you may choose any version +ever published by the Free Software Foundation. + +14. If you wish to incorporate parts of the Library into other free programs +whose distribution conditions are incompatible with these, write to the author +to ask for permission. For software which is copyrighted by the Free Software +Foundation, write to the Free Software Foundation; we sometimes make exceptions +for this. Our decision will be guided by the two goals of preserving the free +status of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + +15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY +"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE +OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE +THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE +OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA +OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES +OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH +HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest possible +use to the public, we recommend making it free software that everyone can +redistribute and change. You can do so by permitting redistribution under +these terms (or, alternatively, under the terms of the ordinary General Public +License). + +To apply these terms, attach the following notices to the library. It is safest +to attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the "copyright" +line and a pointer to where the full notice is found. + +one line to give the library's name and an idea of what it does. + +Copyright (C) year name of author + +This library is free software; you can redistribute it and/or modify it under +the terms of the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your option) +any later version. + +This library is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +details. + +You should have received a copy of the GNU Library General Public License +along with this library; if not, write to the Free Software Foundation, Inc., +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the library, if necessary. Here +is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in + +the library `Frob' (a library for tweaking knobs) written + +by James Random Hacker. + +signature of Ty Coon, 1 April 1990 + +Ty Coon, President of Vice + +That's all there is to it! diff --git a/LICENSES/LGPL-2.1-only.txt b/LICENSES/LGPL-2.1-only.txt new file mode 100644 index 0000000..130dffb --- /dev/null +++ b/LICENSES/LGPL-2.1-only.txt @@ -0,0 +1,467 @@ +GNU LESSER GENERAL PUBLIC LICENSE + +Version 2.1, February 1999 + +Copyright (C) 1991, 1999 Free Software Foundation, Inc. + +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts as the +successor of the GNU Library Public License, version 2, hence the version +number 2.1.] + +Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public Licenses are intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. + +This license, the Lesser General Public License, applies to some specially +designated software packages--typically libraries--of the Free Software Foundation +and other authors who decide to use it. You can use it too, but we suggest +you first think carefully about whether this license or the ordinary General +Public License is the better strategy to use in any particular case, based +on the explanations below. + +When we speak of free software, we are referring to freedom of use, not price. +Our General Public Licenses are designed to make sure that you have the freedom +to distribute copies of free software (and charge for this service if you +wish); that you receive source code or can get it if you want it; that you +can change the software and use pieces of it in new free programs; and that +you are informed that you can do these things. + +To protect your rights, we need to make restrictions that forbid distributors +to deny you these rights or to ask you to surrender these rights. These restrictions +translate to certain responsibilities for you if you distribute copies of +the library or if you modify it. + +For example, if you distribute copies of the library, whether gratis or for +a fee, you must give the recipients all the rights that we gave you. You must +make sure that they, too, receive or can get the source code. If you link +other code with the library, you must provide complete object files to the +recipients, so that they can relink them with the library after making changes +to the library and recompiling it. And you must show them these terms so they +know their rights. + +We protect your rights with a two-step method: (1) we copyright the library, +and (2) we offer you this license, which gives you legal permission to copy, +distribute and/or modify the library. + +To protect each distributor, we want to make it very clear that there is no +warranty for the free library. Also, if the library is modified by someone +else and passed on, the recipients should know that what they have is not +the original version, so that the original author's reputation will not be +affected by problems that might be introduced by others. + +Finally, software patents pose a constant threat to the existence of any free +program. We wish to make sure that a company cannot effectively restrict the +users of a free program by obtaining a restrictive license from a patent holder. +Therefore, we insist that any patent license obtained for a version of the +library must be consistent with the full freedom of use specified in this +license. + +Most GNU software, including some libraries, is covered by the ordinary GNU +General Public License. This license, the GNU Lesser General Public License, +applies to certain designated libraries, and is quite different from the ordinary +General Public License. We use this license for certain libraries in order +to permit linking those libraries into non-free programs. + +When a program is linked with a library, whether statically or using a shared +library, the combination of the two is legally speaking a combined work, a +derivative of the original library. The ordinary General Public License therefore +permits such linking only if the entire combination fits its criteria of freedom. +The Lesser General Public License permits more lax criteria for linking other +code with the library. + +We call this license the "Lesser" General Public License because it does Less +to protect the user's freedom than the ordinary General Public License. It +also provides other free software developers Less of an advantage over competing +non-free programs. These disadvantages are the reason we use the ordinary +General Public License for many libraries. However, the Lesser license provides +advantages in certain special circumstances. + +For example, on rare occasions, there may be a special need to encourage the +widest possible use of a certain library, so that it becomes a de-facto standard. +To achieve this, non-free programs must be allowed to use the library. A more +frequent case is that a free library does the same job as widely used non-free +libraries. In this case, there is little to gain by limiting the free library +to free software only, so we use the Lesser General Public License. + +In other cases, permission to use a particular library in non-free programs +enables a greater number of people to use a large body of free software. For +example, permission to use the GNU C Library in non-free programs enables +many more people to use the whole GNU operating system, as well as its variant, +the GNU/Linux operating system. + +Although the Lesser General Public License is Less protective of the users' +freedom, it does ensure that the user of a program that is linked with the +Library has the freedom and the wherewithal to run that program using a modified +version of the Library. + +The precise terms and conditions for copying, distribution and modification +follow. Pay close attention to the difference between a "work based on the +library" and a "work that uses the library". The former contains code derived +from the library, whereas the latter must be combined with the library in +order to run. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License Agreement applies to any software library or other program +which contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Lesser General +Public License (also called "this License"). Each licensee is addressed as +"you". + +A "library" means a collection of software functions and/or data prepared +so as to be conveniently linked with application programs (which use some +of those functions and data) to form executables. + +The "Library", below, refers to any such software library or work which has +been distributed under these terms. A "work based on the Library" means either +the Library or any derivative work under copyright law: that is to say, a +work containing the Library or a portion of it, either verbatim or with modifications +and/or translated straightforwardly into another language. (Hereinafter, translation +is included without limitation in the term "modification".) + +"Source code" for a work means the preferred form of the work for making modifications +to it. For a library, complete source code means all the source code for all +modules it contains, plus any associated interface definition files, plus +the scripts used to control compilation and installation of the library. + +Activities other than copying, distribution and modification are not covered +by this License; they are outside its scope. The act of running a program +using the Library is not restricted, and output from such a program is covered +only if its contents constitute a work based on the Library (independent of +the use of the Library in a tool for writing it). Whether that is true depends +on what the Library does and what the program that uses the Library does. + +1. You may copy and distribute verbatim copies of the Library's complete source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and disclaimer +of warranty; keep intact all the notices that refer to this License and to +the absence of any warranty; and distribute a copy of this License along with +the Library. + +You may charge a fee for the physical act of transferring a copy, and you +may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Library or any portion of it, +thus forming a work based on the Library, and copy and distribute such modifications +or work under the terms of Section 1 above, provided that you also meet all +of these conditions: + + a) The modified work must itself be a software library. + +b) You must cause the files modified to carry prominent notices stating that +you changed the files and the date of any change. + +c) You must cause the whole of the work to be licensed at no charge to all +third parties under the terms of this License. + +d) If a facility in the modified Library refers to a function or a table of +data to be supplied by an application program that uses the facility, other +than as an argument passed when the facility is invoked, then you must make +a good faith effort to ensure that, in the event an application does not supply +such function or table, the facility still operates, and performs whatever +part of its purpose remains meaningful. + +(For example, a function in a library to compute square roots has a purpose +that is entirely well-defined independent of the application. Therefore, Subsection +2d requires that any application-supplied function or table used by this function +must be optional: if the application does not supply it, the square root function +must still compute square roots.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Library, and can be reasonably +considered independent and separate works in themselves, then this License, +and its terms, do not apply to those sections when you distribute them as +separate works. But when you distribute the same sections as part of a whole +which is a work based on the Library, the distribution of the whole must be +on the terms of this License, whose permissions for other licensees extend +to the entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise +the right to control the distribution of derivative or collective works based +on the Library. + +In addition, mere aggregation of another work not based on the Library with +the Library (or with a work based on the Library) on a volume of a storage +or distribution medium does not bring the other work under the scope of this +License. + +3. You may opt to apply the terms of the ordinary GNU General Public License +instead of this License to a given copy of the Library. To do this, you must +alter all the notices that refer to this License, so that they refer to the +ordinary GNU General Public License, version 2, instead of to this License. +(If a newer version than version 2 of the ordinary GNU General Public License +has appeared, then you can specify that version instead if you wish.) Do not +make any other change in these notices. + +Once this change is made in a given copy, it is irreversible for that copy, +so the ordinary GNU General Public License applies to all subsequent copies +and derivative works made from that copy. + +This option is useful when you wish to copy part of the code of the Library +into a program that is not a library. + +4. You may copy and distribute the Library (or a portion or derivative of +it, under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you accompany it with the complete corresponding +machine-readable source code, which must be distributed under the terms of +Sections 1 and 2 above on a medium customarily used for software interchange. + +If distribution of object code is made by offering access to copy from a designated +place, then offering equivalent access to copy the source code from the same +place satisfies the requirement to distribute the source code, even though +third parties are not compelled to copy the source along with the object code. + +5. A program that contains no derivative of any portion of the Library, but +is designed to work with the Library by being compiled or linked with it, +is called a "work that uses the Library". Such a work, in isolation, is not +a derivative work of the Library, and therefore falls outside the scope of +this License. + +However, linking a "work that uses the Library" with the Library creates an +executable that is a derivative of the Library (because it contains portions +of the Library), rather than a "work that uses the library". The executable +is therefore covered by this License. Section 6 states terms for distribution +of such executables. + +When a "work that uses the Library" uses material from a header file that +is part of the Library, the object code for the work may be a derivative work +of the Library even though the source code is not. Whether this is true is +especially significant if the work can be linked without the Library, or if +the work is itself a library. The threshold for this to be true is not precisely +defined by law. + +If such an object file uses only numerical parameters, data structure layouts +and accessors, and small macros and small inline functions (ten lines or less +in length), then the use of the object file is unrestricted, regardless of +whether it is legally a derivative work. (Executables containing this object +code plus portions of the Library will still fall under Section 6.) + +Otherwise, if the work is a derivative of the Library, you may distribute +the object code for the work under the terms of Section 6. Any executables +containing that work also fall under Section 6, whether or not they are linked +directly with the Library itself. + +6. As an exception to the Sections above, you may also combine or link a "work +that uses the Library" with the Library to produce a work containing portions +of the Library, and distribute that work under terms of your choice, provided +that the terms permit modification of the work for the customer's own use +and reverse engineering for debugging such modifications. + +You must give prominent notice with each copy of the work that the Library +is used in it and that the Library and its use are covered by this License. +You must supply a copy of this License. If the work during execution displays +copyright notices, you must include the copyright notice for the Library among +them, as well as a reference directing the user to the copy of this License. +Also, you must do one of these things: + +a) Accompany the work with the complete corresponding machine-readable source +code for the Library including whatever changes were used in the work (which +must be distributed under Sections 1 and 2 above); and, if the work is an +executable linked with the Library, with the complete machine-readable "work +that uses the Library", as object code and/or source code, so that the user +can modify the Library and then relink to produce a modified executable containing +the modified Library. (It is understood that the user who changes the contents +of definitions files in the Library will not necessarily be able to recompile +the application to use the modified definitions.) + +b) Use a suitable shared library mechanism for linking with the Library. A +suitable mechanism is one that (1) uses at run time a copy of the library +already present on the user's computer system, rather than copying library +functions into the executable, and (2) will operate properly with a modified +version of the library, if the user installs one, as long as the modified +version is interface-compatible with the version that the work was made with. + +c) Accompany the work with a written offer, valid for at least three years, +to give the same user the materials specified in Subsection 6a, above, for +a charge no more than the cost of performing this distribution. + +d) If distribution of the work is made by offering access to copy from a designated +place, offer equivalent access to copy the above specified materials from +the same place. + +e) Verify that the user has already received a copy of these materials or +that you have already sent this user a copy. + +For an executable, the required form of the "work that uses the Library" must +include any data and utility programs needed for reproducing the executable +from it. However, as a special exception, the materials to be distributed +need not include anything that is normally distributed (in either source or +binary form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component itself +accompanies the executable. + +It may happen that this requirement contradicts the license restrictions of +other proprietary libraries that do not normally accompany the operating system. +Such a contradiction means you cannot use both them and the Library together +in an executable that you distribute. + +7. You may place library facilities that are a work based on the Library side-by-side +in a single library together with other library facilities not covered by +this License, and distribute such a combined library, provided that the separate +distribution of the work based on the Library and of the other library facilities +is otherwise permitted, and provided that you do these two things: + +a) Accompany the combined library with a copy of the same work based on the +Library, uncombined with any other library facilities. This must be distributed +under the terms of the Sections above. + +b) Give prominent notice with the combined library of the fact that part of +it is a work based on the Library, and explaining where to find the accompanying +uncombined form of the same work. + +8. You may not copy, modify, sublicense, link with, or distribute the Library +except as expressly provided under this License. Any attempt otherwise to +copy, modify, sublicense, link with, or distribute the Library is void, and +will automatically terminate your rights under this License. However, parties +who have received copies, or rights, from you under this License will not +have their licenses terminated so long as such parties remain in full compliance. + +9. You are not required to accept this License, since you have not signed +it. However, nothing else grants you permission to modify or distribute the +Library or its derivative works. These actions are prohibited by law if you +do not accept this License. Therefore, by modifying or distributing the Library +(or any work based on the Library), you indicate your acceptance of this License +to do so, and all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + +10. Each time you redistribute the Library (or any work based on the Library), +the recipient automatically receives a license from the original licensor +to copy, distribute, link with or modify the Library subject to these terms +and conditions. You may not impose any further restrictions on the recipients' +exercise of the rights granted herein. You are not responsible for enforcing +compliance by third parties with this License. + +11. If, as a consequence of a court judgment or allegation of patent infringement +or for any other reason (not limited to patent issues), conditions are imposed +on you (whether by court order, agreement or otherwise) that contradict the +conditions of this License, they do not excuse you from the conditions of +this License. If you cannot distribute so as to satisfy simultaneously your +obligations under this License and any other pertinent obligations, then as +a consequence you may not distribute the Library at all. For example, if a +patent license would not permit royalty-free redistribution of the Library +by all those who receive copies directly or indirectly through you, then the +only way you could satisfy both it and this License would be to refrain entirely +from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents +or other property right claims or to contest validity of any such claims; +this section has the sole purpose of protecting the integrity of the free +software distribution system which is implemented by public license practices. +Many people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose +that choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +12. If the distribution and/or use of the Library is restricted in certain +countries either by patents or by copyrighted interfaces, the original copyright +holder who places the Library under this License may add an explicit geographical +distribution limitation excluding those countries, so that distribution is +permitted only in or among countries not thus excluded. In such case, this +License incorporates the limitation as if written in the body of this License. + +13. The Free Software Foundation may publish revised and/or new versions of +the Lesser General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to address +new problems or concerns. + +Each version is given a distinguishing version number. If the Library specifies +a version number of this License which applies to it and "any later version", +you have the option of following the terms and conditions either of that version +or of any later version published by the Free Software Foundation. If the +Library does not specify a license version number, you may choose any version +ever published by the Free Software Foundation. + +14. If you wish to incorporate parts of the Library into other free programs +whose distribution conditions are incompatible with these, write to the author +to ask for permission. For software which is copyrighted by the Free Software +Foundation, write to the Free Software Foundation; we sometimes make exceptions +for this. Our decision will be guided by the two goals of preserving the free +status of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + +15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY +"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE +OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE +THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE +OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA +OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES +OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH +HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest possible +use to the public, we recommend making it free software that everyone can +redistribute and change. You can do so by permitting redistribution under +these terms (or, alternatively, under the terms of the ordinary General Public +License). + +To apply these terms, attach the following notices to the library. It is safest +to attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the "copyright" +line and a pointer to where the full notice is found. + +< one line to give the library's name and an idea of what it does. > + +Copyright (C) < year > < name of author > + +This library is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published by the Free +Software Foundation; either version 2.1 of the License, or (at your option) +any later version. + +This library is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. + +You should have received a copy of the GNU Lesser General Public License along +with this library; if not, write to the Free Software Foundation, Inc., 51 +Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information +on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the library, if necessary. Here +is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in + +the library `Frob' (a library for tweaking knobs) written + +by James Random Hacker. + +< signature of Ty Coon > , 1 April 1990 + +Ty Coon, President of Vice + +That's all there is to it! diff --git a/LICENSES/LGPL-3.0-only.txt b/LICENSES/LGPL-3.0-only.txt new file mode 100644 index 0000000..bd405af --- /dev/null +++ b/LICENSES/LGPL-3.0-only.txt @@ -0,0 +1,163 @@ +GNU LESSER GENERAL PUBLIC LICENSE + +Version 3, 29 June 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +This version of the GNU Lesser General Public License incorporates the terms +and conditions of version 3 of the GNU General Public License, supplemented +by the additional permissions listed below. + + 0. Additional Definitions. + + + +As used herein, "this License" refers to version 3 of the GNU Lesser General +Public License, and the "GNU GPL" refers to version 3 of the GNU General Public +License. + + + +"The Library" refers to a covered work governed by this License, other than +an Application or a Combined Work as defined below. + + + +An "Application" is any work that makes use of an interface provided by the +Library, but which is not otherwise based on the Library. Defining a subclass +of a class defined by the Library is deemed a mode of using an interface provided +by the Library. + + + +A "Combined Work" is a work produced by combining or linking an Application +with the Library. The particular version of the Library with which the Combined +Work was made is also called the "Linked Version". + + + +The "Minimal Corresponding Source" for a Combined Work means the Corresponding +Source for the Combined Work, excluding any source code for portions of the +Combined Work that, considered in isolation, are based on the Application, +and not on the Linked Version. + + + +The "Corresponding Application Code" for a Combined Work means the object +code and/or source code for the Application, including any data and utility +programs needed for reproducing the Combined Work from the Application, but +excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + +You may convey a covered work under sections 3 and 4 of this License without +being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + +If you modify a copy of the Library, and, in your modifications, a facility +refers to a function or data to be supplied by an Application that uses the +facility (other than as an argument passed when the facility is invoked), +then you may convey a copy of the modified version: + +a) under this License, provided that you make a good faith effort to ensure +that, in the event an Application does not supply the function or data, the +facility still operates, and performs whatever part of its purpose remains +meaningful, or + +b) under the GNU GPL, with none of the additional permissions of this License +applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + +The object code form of an Application may incorporate material from a header +file that is part of the Library. You may convey such object code under terms +of your choice, provided that, if the incorporated material is not limited +to numerical parameters, data structure layouts and accessors, or small macros, +inline functions and templates (ten or fewer lines in length), you do both +of the following: + +a) Give prominent notice with each copy of the object code that the Library +is used in it and that the Library and its use are covered by this License. + +b) Accompany the object code with a copy of the GNU GPL and this license document. + + 4. Combined Works. + +You may convey a Combined Work under terms of your choice that, taken together, +effectively do not restrict modification of the portions of the Library contained +in the Combined Work and reverse engineering for debugging such modifications, +if you also do each of the following: + +a) Give prominent notice with each copy of the Combined Work that the Library +is used in it and that the Library and its use are covered by this License. + +b) Accompany the Combined Work with a copy of the GNU GPL and this license +document. + +c) For a Combined Work that displays copyright notices during execution, include +the copyright notice for the Library among these notices, as well as a reference +directing the user to the copies of the GNU GPL and this license document. + + d) Do one of the following: + +0) Convey the Minimal Corresponding Source under the terms of this License, +and the Corresponding Application Code in a form suitable for, and under terms +that permit, the user to recombine or relink the Application with a modified +version of the Linked Version to produce a modified Combined Work, in the +manner specified by section 6 of the GNU GPL for conveying Corresponding Source. + +1) Use a suitable shared library mechanism for linking with the Library. A +suitable mechanism is one that (a) uses at run time a copy of the Library +already present on the user's computer system, and (b) will operate properly +with a modified version of the Library that is interface-compatible with the +Linked Version. + +e) Provide Installation Information, but only if you would otherwise be required +to provide such information under section 6 of the GNU GPL, and only to the +extent that such information is necessary to install and execute a modified +version of the Combined Work produced by recombining or relinking the Application +with a modified version of the Linked Version. (If you use option 4d0, the +Installation Information must accompany the Minimal Corresponding Source and +Corresponding Application Code. If you use option 4d1, you must provide the +Installation Information in the manner specified by section 6 of the GNU GPL +for conveying Corresponding Source.) + + 5. Combined Libraries. + +You may place library facilities that are a work based on the Library side +by side in a single library together with other library facilities that are +not Applications and are not covered by this License, and convey such a combined +library under terms of your choice, if you do both of the following: + +a) Accompany the combined library with a copy of the same work based on the +Library, uncombined with any other library facilities, conveyed under the +terms of this License. + +b) Give prominent notice with the combined library that part of it is a work +based on the Library, and explaining where to find the accompanying uncombined +form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + +The Free Software Foundation may publish revised and/or new versions of the +GNU Lesser General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to address +new problems or concerns. + +Each version is given a distinguishing version number. If the Library as you +received it specifies that a certain numbered version of the GNU Lesser General +Public License "or any later version" applies to it, you have the option of +following the terms and conditions either of that published version or of +any later version published by the Free Software Foundation. If the Library +as you received it does not specify a version number of the GNU Lesser General +Public License, you may choose any version of the GNU Lesser General Public +License ever published by the Free Software Foundation. + +If the Library as you received it specifies that a proxy can decide whether +future versions of the GNU Lesser General Public License shall apply, that +proxy's public statement of acceptance of any version is permanent authorization +for you to choose that version for the Library. diff --git a/LICENSES/LicenseRef-KDE-Accepted-LGPL.txt b/LICENSES/LicenseRef-KDE-Accepted-LGPL.txt new file mode 100644 index 0000000..232b3c5 --- /dev/null +++ b/LICENSES/LicenseRef-KDE-Accepted-LGPL.txt @@ -0,0 +1,12 @@ +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the license or (at your option) any later version +that is accepted by the membership of KDE e.V. (or its successor +approved by the membership of KDE e.V.), which shall act as a +proxy as defined in Section 6 of version 3 of the license. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c0accdb --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# KDESU + +User interface for running shell commands with root privileges + +## Introduction + +KDESU provides functionality for building GUI front ends for +(password asking) console mode programs. For example, kdesu and +kdessh use it to interface with su and ssh respectively. + diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt new file mode 100644 index 0000000..a8aace8 --- /dev/null +++ b/autotests/CMakeLists.txt @@ -0,0 +1,10 @@ +include(ECMAddTests) +find_package(Qt${QT_MAJOR_VERSION}Test REQUIRED) +configure_file(config-kdesutest.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kdesutest.h) +ecm_add_test(kdesutest.cpp TEST_NAME kdesutest LINK_LIBRARIES Qt${QT_MAJOR_VERSION}::Test KF5::Su KF5::CoreAddons KF5::ConfigCore) + +if(KDESU_USE_SUDO_DEFAULT) + target_compile_definitions(kdesutest PRIVATE -DKDESU_USE_SUDO_DEFAULT="true") +elseif(KDESU_USE_DOAS_DEFAULT) + target_compile_definitions(kdesutest PRIVATE -DKDESU_USE_DOAS_DEFAULT="true") +endif() diff --git a/autotests/config-kdesutest.h.cmake b/autotests/config-kdesutest.h.cmake new file mode 100644 index 0000000..5f320cc --- /dev/null +++ b/autotests/config-kdesutest.h.cmake @@ -0,0 +1,2 @@ +#define CMAKE_HOME_DIRECTORY "${CMAKE_HOME_DIRECTORY}" +#define CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" diff --git a/autotests/kdesutest.cpp b/autotests/kdesutest.cpp new file mode 100644 index 0000000..1ff7081 --- /dev/null +++ b/autotests/kdesutest.cpp @@ -0,0 +1,111 @@ +/* + SPDX-FileCopyrightText: 2019 Jonathan Riddell + + SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +*/ + +#define MYPASSWORD "ilovekde" +#define ROOTPASSWORD "ilovekde" +#include "config-kdesutest.h" + +#include +#include +#include + +#include +#include +#include + +#include "suprocess.h" + +namespace KDESu +{ +class KdeSuTest : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void initTestCase() + { + QStandardPaths::setTestModeEnabled(true); + } + + void editConfig(QString command, QString commandPath) + { + KSharedConfig::Ptr config = KSharedConfig::openConfig(); + KConfigGroup group(config, "super-user-command"); + group.writeEntry("super-user-command", command); + QString kdesuStubPath = QString::fromLocal8Bit(CMAKE_RUNTIME_OUTPUT_DIRECTORY) + QString::fromLocal8Bit("/kdesu_stub"); + group.writeEntry("kdesu_stub_path", kdesuStubPath); + group.writeEntry("command", commandPath); + } + + void sudoGoodPassword() + { + editConfig(QString::fromLocal8Bit("sudo"), QString::fromLocal8Bit(CMAKE_HOME_DIRECTORY) + QString::fromLocal8Bit("/autotests/sudo")); + + KDESu::SuProcess suProcess("root", "ls"); + QString suapp = suProcess.superUserCommand(); + QVERIFY(suapp == QLatin1String("sudo")); + int result = suProcess.exec(MYPASSWORD, 0); + QVERIFY(result == 0); + } + + void sudoBadPassword() + { + editConfig(QString::fromLocal8Bit("sudo"), QString::fromLocal8Bit(CMAKE_HOME_DIRECTORY) + QString::fromLocal8Bit("/autotests/sudo")); + + KDESu::SuProcess suProcess("root", "ls"); + QString suapp = suProcess.superUserCommand(); + QVERIFY(suapp == QLatin1String("sudo")); + int result2 = suProcess.exec("broken", 0); + QVERIFY(result2 == KDESu::SuProcess::SuIncorrectPassword); + } + + void doasBadPassword() + { + editConfig(QString::fromLocal8Bit("doas"), QString::fromLocal8Bit(CMAKE_HOME_DIRECTORY) + QString::fromLocal8Bit("/autotests/sudo")); + + KDESu::SuProcess suProcess("root", "ls"); + QString suapp = suProcess.superUserCommand(); + QVERIFY(suapp == QLatin1String("doas")); + int result2 = suProcess.exec("broken", 0); + QVERIFY(result2 == KDESu::SuProcess::SuIncorrectPassword); + } + + void doasGoodPassword() + { + editConfig(QString::fromLocal8Bit("doas"), QString::fromLocal8Bit(CMAKE_HOME_DIRECTORY) + QString::fromLocal8Bit("/autotests/sudo")); + + KDESu::SuProcess suProcess("root", "ls"); + QString suapp = suProcess.superUserCommand(); + QVERIFY(suapp == QLatin1String("doas")); + int result = suProcess.exec(MYPASSWORD, 0); + QVERIFY(result == 0); + } + + void suGoodPassword() + { + editConfig(QString::fromLocal8Bit("su"), QString::fromLocal8Bit(CMAKE_HOME_DIRECTORY) + QString::fromLocal8Bit("/autotests/su")); + + KDESu::SuProcess suProcess("root", "ls"); + QString suapp = suProcess.superUserCommand(); + QVERIFY(suapp == QLatin1String("su")); + int result2 = suProcess.exec(ROOTPASSWORD, 0); + QVERIFY(result2 == 0); + } + + void suBadPassword() + { + editConfig(QString::fromLocal8Bit("su"), QString::fromLocal8Bit(CMAKE_HOME_DIRECTORY) + QString::fromLocal8Bit("/autotests/su")); + + KDESu::SuProcess suProcess("root", "ls"); + QString suapp = suProcess.superUserCommand(); + QVERIFY(suapp == QLatin1String("su")); + int result2 = suProcess.exec("broken", 0); + QVERIFY(result2 == KDESu::SuProcess::SuIncorrectPassword); + } +}; +} + +#include +QTEST_MAIN(KDESu::KdeSuTest) diff --git a/autotests/su b/autotests/su new file mode 100755 index 0000000..0e4f7cf --- /dev/null +++ b/autotests/su @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 + +import sys +import getpass +from enum import Enum, unique +from subprocess import call + + +@unique +class State(Enum): + NEW = 1 + SECOND = 2 + THIRD = 3 + GOOD = 4 + FAIL = 5 + +class Su: + + def __init__(self): + self.state = State.NEW + self.read = None + self.password = 'ilovekde' + + def process(self): + if self.state == State.NEW: + self.read = getpass.getpass('Password: ') + if self.read == self.password: + self.state = State.GOOD + call([sys.argv[3]]) + exit(0) + else: + self.state = State.FAIL + print("su: Authentication failure") + exit(1) + +su = Su() +while True: + su.process() diff --git a/autotests/sudo b/autotests/sudo new file mode 100755 index 0000000..ad36e18 --- /dev/null +++ b/autotests/sudo @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +import sys +import getpass +from enum import Enum, unique +from subprocess import call + + +@unique +class State(Enum): + NEW = 1 + SECOND = 2 + THIRD = 3 + GOOD = 4 + FAIL = 5 + +class Sudo: + + def __init__(self): + self.state = State.NEW + self.read = None + self.password = 'ilovekde' + + def process(self): + if self.state == State.NEW: + self.read = getpass.getpass('[sudo] password for jr: ') + if self.read == self.password: + self.state = State.GOOD + call([sys.argv[3]]) + exit(0) + else: + self.state = State.SECOND + elif self.state == State.SECOND: + print('Sorry, try again.') + self.read = getpass.getpass('[sudo] password for jr: ') + if self.read == self.password: + self.state = State.GOOD + exit(0) + else: + self.state = State.THIRD + elif self.state == State.THIRD: + print('Sorry, try again.') + self.read = getpass.getpass('[sudo] password for jr: ') + if self.read == self.password: + self.state = State.GOOD + exit(0) + else: + print("sudo: 3 incorrect password attempts") + self.state = State.FAIL + exit(1) + +sudo = Sudo() +while True: + sudo.process() diff --git a/docs/Doxyfile.local b/docs/Doxyfile.local new file mode 100644 index 0000000..32bae07 --- /dev/null +++ b/docs/Doxyfile.local @@ -0,0 +1,7 @@ +### KApiDox Project-specific Overrides File + +# define so that deprecated API is not skipped +PREDEFINED += \ + "KDESU_ENABLE_DEPRECATED_SINCE(x, y)=1" \ + "KDESU_BUILD_DEPRECATED_SINCE(x, y)=1" \ + "KDESU_DEPRECATED_VERSION(x, y, t)=" diff --git a/metainfo.yaml b/metainfo.yaml new file mode 100644 index 0000000..6d59e5b --- /dev/null +++ b/metainfo.yaml @@ -0,0 +1,18 @@ +maintainer: +description: Integration with su for elevated privileges +tier: 3 +type: integration +platforms: + - name: Linux + - name: FreeBSD +portingAid: false +deprecated: false +release: true +libraries: + - qmake: KDESu + cmake: "KF5::Su" +cmakename: KF5Su + +public_lib: true +group: Frameworks +subgroup: Tier 3 diff --git a/po/ar/kdesud5.po b/po/ar/kdesud5.po new file mode 100644 index 0000000..6a3af1f --- /dev/null +++ b/po/ar/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# Safa Alfulaij , 2014, 2018. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2018-06-08 23:53+0300\n" +"Last-Translator: Safa Alfulaij \n" +"Language-Team: Arabic \n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" +"X-Generator: Lokalize 2.0\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "صفا الفليج" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "safa1996alfulaij@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "عفريت كدي لِ‍ su" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "عفريت تستخدمه kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "‏© ١٩٩٩،٢٠٠٠ Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "المؤلف" diff --git a/po/ast/kdesud5.po b/po/ast/kdesud5.po new file mode 100644 index 0000000..d80e368 --- /dev/null +++ b/po/ast/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdesu package. +# +# enolp , 2019. +msgid "" +msgstr "" +"Project-Id-Version: kdesu\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2019-08-16 07:06+0200\n" +"Last-Translator: enolp \n" +"Language-Team: Asturian \n" +"Language: ast\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 19.04.3\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Softastur" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "alministradores@softastur.org" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Degorriu pa su de KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "El degorriu usáu por kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/az/kdesud5.po b/po/az/kdesud5.po new file mode 100644 index 0000000..1fd75dc --- /dev/null +++ b/po/az/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdesu package. +# +# Xəyyam , 2020. +msgid "" +msgstr "" +"Project-Id-Version: kdesu\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2020-07-16 08:52+0400\n" +"Last-Translator: Xəyyam Qocayev \n" +"Language-Team: Azerbaijani \n" +"Language: az\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 20.04.3\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Xəyyam Qocayev" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "xxmn77@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su vasitəsi" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "kdesu tərəfindən istifadə olunan vasitə" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Müəllif" diff --git a/po/bs/kdesud5.po b/po/bs/kdesud5.po new file mode 100644 index 0000000..741308f --- /dev/null +++ b/po/bs/kdesud5.po @@ -0,0 +1,55 @@ +# Bosnian translations for PACKAGE package +# engleski prevodi za paket PACKAGE. +# Copyright (C) 2015 This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# Samir ribic , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: kde5\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2015-02-24 19:45+0100\n" +"Last-Translator: Samir Ribić \n" +"Language-Team: Bosnian\n" +"Language: bs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Samir Ribić" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "samir.ribic@etf.unsa.ba" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su demon" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Demon koji koristi kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Gert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/ca/kdesud5.po b/po/ca/kdesud5.po new file mode 100644 index 0000000..ac7c589 --- /dev/null +++ b/po/ca/kdesud5.po @@ -0,0 +1,57 @@ +# Translation of kdesud5.po to Catalan +# Copyright (C) 2014 This_file_is_part_of_KDE +# This file is distributed under the license LGPL version 2.1 or +# version 3 or later versions approved by the membership of KDE e.V. +# +# Josep M. Ferrer , 2014. +# Antoni Bella Pérez , 2014. +msgid "" +msgstr "" +"Project-Id-Version: kdesu\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-06-25 15:58+0200\n" +"Last-Translator: Antoni Bella Pérez \n" +"Language-Team: Catalan \n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Accelerator-Marker: &\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Josep M. Ferrer" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "txemaq@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Dimoni «su» del KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Dimoni usat pel kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999, 2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/ca@valencia/kdesud5.po b/po/ca@valencia/kdesud5.po new file mode 100644 index 0000000..99a6a8e --- /dev/null +++ b/po/ca@valencia/kdesud5.po @@ -0,0 +1,57 @@ +# Translation of kdesud5.po to Catalan (Valencian) +# Copyright (C) 2014 This_file_is_part_of_KDE +# This file is distributed under the license LGPL version 2.1 or +# version 3 or later versions approved by the membership of KDE e.V. +# +# Josep M. Ferrer , 2014. +# Antoni Bella Pérez , 2014. +msgid "" +msgstr "" +"Project-Id-Version: kdesu\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-06-25 15:58+0200\n" +"Last-Translator: Antoni Bella Pérez \n" +"Language-Team: Catalan \n" +"Language: ca@valencia\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Accelerator-Marker: &\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Josep M. Ferrer" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "txemaq@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Dimoni «su» del KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Dimoni usat pel kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999, 2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/cs/kdesud5.po b/po/cs/kdesud5.po new file mode 100644 index 0000000..927aff6 --- /dev/null +++ b/po/cs/kdesud5.po @@ -0,0 +1,53 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2007-10-04 17:03+0200\n" +"Last-Translator: Lukáš Tinkl \n" +"Language-Team: Czech \n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Lukáš Tinkl" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "lukas@kde.org" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Démon kdesu" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Démon používaný kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/da/kdesud5.po b/po/da/kdesud5.po new file mode 100644 index 0000000..eda1ad2 --- /dev/null +++ b/po/da/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Martin Schlander , 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-09-21 15:38+0200\n" +"Last-Translator: Martin Schlander \n" +"Language-Team: Danish \n" +"Language: da\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Martin Schlander" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "mschlander@opensuse.org" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su-dæmon" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Dæmon som bruges af kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Ophavsret (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Ophavsmand" diff --git a/po/de/kdesud5.po b/po/de/kdesud5.po new file mode 100644 index 0000000..01c74af --- /dev/null +++ b/po/de/kdesud5.po @@ -0,0 +1,49 @@ +# Burkhard Lück , 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-03-29 10:24+0100\n" +"Last-Translator: Burkhard Lück \n" +"Language-Team: German \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Thomas Diehl" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "thd@kde.org" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Der su-Dienst von KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Von kdesu verwendeter Dienst" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright © 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/el/kdesud5.po b/po/el/kdesud5.po new file mode 100644 index 0000000..22d52bf --- /dev/null +++ b/po/el/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Dimitris Kardarakos , 2015. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2015-11-05 16:15+0200\n" +"Last-Translator: Dimitris Kardarakos \n" +"Language-Team: Greek \n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 2.0\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Δημήτρης Καρδαράκος" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "dimkard@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Δαίμονας su του KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Δαίμονας που χρησιμοποιείται από το kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Πνευματικά δικαιώματα (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Συγγραφέας" diff --git a/po/en_GB/kdesud5.po b/po/en_GB/kdesud5.po new file mode 100644 index 0000000..343331b --- /dev/null +++ b/po/en_GB/kdesud5.po @@ -0,0 +1,53 @@ +# translation of kdesud.po to British English +# Copyright (C) 2008 Free Software Foundation, Inc. +# Malcolm Hunter , 2008. +# Andrew Coles , 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2009-02-26 18:44+0000\n" +"Last-Translator: Andrew Coles \n" +"Language-Team: British English \n" +"Language: en_GB\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Aston Clulow" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "clulow@upnaway.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su dæmon" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Dæmon used by kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Author" diff --git a/po/es/kdesud5.po b/po/es/kdesud5.po new file mode 100644 index 0000000..d393353 --- /dev/null +++ b/po/es/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Eloy Cuadra , 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-03-29 17:43+0100\n" +"Last-Translator: Eloy Cuadra \n" +"Language-Team: Spanish \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Eloy Cuadra" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "ecuadra@eloihr.net" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Demonio «su» de KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Demonio usado por kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright © 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/et/kdesud5.po b/po/et/kdesud5.po new file mode 100644 index 0000000..5a524a9 --- /dev/null +++ b/po/et/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Marek Laane , 2016. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2016-09-09 01:30+0300\n" +"Last-Translator: Marek Laane \n" +"Language-Team: Estonian \n" +"Language: et\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Marek Laane" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "qiilaq69@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su deemon" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Rakenduse kdesu kasutatav deemon" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Autoriõigus (c) 1999,2000: Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/eu/kdesud5.po b/po/eu/kdesud5.po new file mode 100644 index 0000000..1d13bc2 --- /dev/null +++ b/po/eu/kdesud5.po @@ -0,0 +1,56 @@ +# Translation of kdesud5.po to Euskara/Basque (eu) +# Copyright (C) 1999-2017, Free Software Foundation, Inc. +# This file is distributed under the same license as the frameworks package. +# KDE Euskaratzeko proiektuaren arduraduna . +# +# Translators: +# Iñigo Salvador Azurmendi , 2017. +msgid "" +msgstr "" +"Project-Id-Version: kdesud5\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2017-08-24 00:40+0100\n" +"Last-Translator: Iñigo Salvador Azurmendi \n" +"Language-Team: Basque \n" +"Language: eu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 2.0\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Iñigo Salvador Azurmendi" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "Xalba@euskalnet.net" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su daimona" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "kdesu-k erabiltzen duen daimona" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Author" diff --git a/po/fi/kdesud5.po b/po/fi/kdesud5.po new file mode 100644 index 0000000..98dc10e --- /dev/null +++ b/po/fi/kdesud5.po @@ -0,0 +1,55 @@ +# translation of kdesud.po to +# KDE Finnish translation sprint participants: +# Mikko Piippo , 2007. +# Lasse Liehu , 2014. +# Tommi Nieminen , 2020. +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2020-12-19 22:18+0200\n" +"Last-Translator: Tommi Nieminen \n" +"Language-Team: Finnish \n" +"Language: fi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-POT-Import-Date: 2012-12-01 22:22:12+0000\n" +"X-Generator: Lokalize 20.04.2\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Kim Enkovaara, Tommi Nieminen" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "kim.enkovaara@iki.fi, translator@legisign.org" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE:n su-palvelu" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "kdesun käyttämä palvelu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Tekijänoikeudet © 1999, 2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Tekijä" diff --git a/po/fr/kdesud5.po b/po/fr/kdesud5.po new file mode 100644 index 0000000..7da9609 --- /dev/null +++ b/po/fr/kdesud5.po @@ -0,0 +1,56 @@ +# translation of kdesud.po to +# Copyright (C) 2007 Free Software Foundation, Inc. +# aminesay , 2007. +# xavier , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2011-12-30 17:51+0100\n" +"Last-Translator: xavier \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Environment: kde\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "François-Xavier Duranceau, Thibaut Cousin, Amine Say" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "duranceau@kde.org, cousin@kde.org, aminesay@yahoo.fr" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Démon « su » de KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Démon utilisé par « kdesu »" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Auteur" diff --git a/po/gd/kdesud5.po b/po/gd/kdesud5.po new file mode 100644 index 0000000..3187b73 --- /dev/null +++ b/po/gd/kdesud5.po @@ -0,0 +1,55 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# GunChleoc , 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2015-11-04 15:12+0000\n" +"Last-Translator: Michael Bauer \n" +"Language-Team: Fòram na Gàidhlig\n" +"Language: gd\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" +"X-Generator: Poedit 1.8.4\n" +"X-Project-Style: kde\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "GunChleoc" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "fios@foramnagaidhlig.net" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Daemon su airson KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "An daemon a chleachdas kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Còir-lethbhreac (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Ùghdar" diff --git a/po/gl/kdesud5.po b/po/gl/kdesud5.po new file mode 100644 index 0000000..1742c40 --- /dev/null +++ b/po/gl/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Marce Villarino , 2014. +# Adrián Chaves (Gallaecio) , 2017. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2017-10-11 07:14+0100\n" +"Last-Translator: Adrián Chaves (Gallaecio) \n" +"Language-Team: Galician \n" +"Language: gl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Marce Villarino" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "mvillarino@kde-espana.org" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Servizo de su de KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "O servizo usado por kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "© 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/hi/kdesud5.po b/po/hi/kdesud5.po new file mode 100644 index 0000000..40c63cc --- /dev/null +++ b/po/hi/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdesu package. +# +# Sameer Singh , 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdesu\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2021-04-25 17:45+0530\n" +"Last-Translator: Sameer Singh \n" +"Language-Team: Kde-hindi\n" +"Language: hi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" +"X-Generator: Lokalize 21.04.0\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "समीर सिंह" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "lumarzeli30@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "केडीई एसयू डेमन" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "केडीईसयू के द्वारा उपयोग में डेमन" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "सर्वाधिकार (c) १९९९,२००० गीर्त जानसन" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "गीर्त जानसन" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "लेखक" diff --git a/po/hu/kdesud5.po b/po/hu/kdesud5.po new file mode 100644 index 0000000..12ad9aa --- /dev/null +++ b/po/hu/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Kristóf Kiszel , 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-03-29 22:09+0100\n" +"Last-Translator: Kristóf Kiszel \n" +"Language-Team: Hungarian \n" +"Language: hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Kiszel Kristóf" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "ulysses@kubuntu.org" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su szolgáltatás" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "A kdesu által használt szolgáltatás" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "(c) Geert Jansen, 1999, 2000." + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Szerző" diff --git a/po/ia/kdesud5.po b/po/ia/kdesud5.po new file mode 100644 index 0000000..a7fe074 --- /dev/null +++ b/po/ia/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# G.Sora , 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-03-31 16:14+0200\n" +"Last-Translator: G.Sora \n" +"Language-Team: Interlingua \n" +"Language: ia\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Giovanni Sora" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "g.sora@tiscali.it" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Daemon su de KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Daemon usate per kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/id/kdesud5.po b/po/id/kdesud5.po new file mode 100644 index 0000000..6694e17 --- /dev/null +++ b/po/id/kdesud5.po @@ -0,0 +1,54 @@ +# Indonesian translations for kdesud package. +# Copyright (C) 2009 This_file_is_part_of_KDE +# This file is distributed under the same license as the kdesud package. +# Andhika Padmawan , 2009. +# Wantoyo , 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2019-01-18 18:50+0700\n" +"Last-Translator: Wantoyo \n" +"Language-Team: Indonesian \n" +"Language: id\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Andhika Padmawan" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "andhika.padmawan@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Daemon su KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Daemon yang digunakan oleh kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Hak Cipta (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Penulis" diff --git a/po/it/kdesud5.po b/po/it/kdesud5.po new file mode 100644 index 0000000..1fb46fd --- /dev/null +++ b/po/it/kdesud5.po @@ -0,0 +1,52 @@ +# translation of kdesud.po to Italian +# Copyright (C) 2007 Free Software Foundation, Inc. +# Andrea Rizzi , 2007. +# +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2007-09-22 09:50+0200\n" +"Last-Translator: Andrea Rizzi \n" +"Language-Team: Italian \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Federico Cozzi" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "Federico.Cozzi@sns.it" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Demone su di KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Demone usato da Kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autore" diff --git a/po/ja/kdesud5.po b/po/ja/kdesud5.po new file mode 100644 index 0000000..331286a --- /dev/null +++ b/po/ja/kdesud5.po @@ -0,0 +1,55 @@ +# Translation of kdesud into Japanese. +# This file is distributed under the same license as the kdebase package. +# Sinohara , 2001. +# +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2001-01-10 23:12GMT\n" +"Last-Translator: Sinohara \n" +"Language-Team: Japanese \n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 0.7.1\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Noboru Sinohara" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "shinobo@leo.bekkoame.ne.jp" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su デーモン" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "kdesu が使用するデーモン" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "作者" diff --git a/po/ko/kdesud5.po b/po/ko/kdesud5.po new file mode 100644 index 0000000..31f41be --- /dev/null +++ b/po/ko/kdesud5.po @@ -0,0 +1,53 @@ +# Translation of kdesud to Korean. +# Copyright (C) 2001, 2007. +# Yu-Chan, Park , 2001. +# Shinjo Park , 2007. +# +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2007-12-01 15:16+0900\n" +"Last-Translator: Shinjo Park \n" +"Language-Team: Korean \n" +"Language: ko\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "박신조" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "kde@peremen.name" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su 데몬" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "kdesu에서 사용하는 데몬" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "작성자" diff --git a/po/lt/kdesud5.po b/po/lt/kdesud5.po new file mode 100644 index 0000000..0be5c26 --- /dev/null +++ b/po/lt/kdesud5.po @@ -0,0 +1,56 @@ +# Lithuanian translations for trunk-kf package. +# Copyright (C) 2014 This_file_is_part_of_KDE +# This file is distributed under the same license as the trunk-kf package. +# +# Automatically generated, 2014. +# Liudas Ališauskas , 2014. +msgid "" +msgstr "" +"Project-Id-Version: trunk-kf 5\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-11-11 00:15+0200\n" +"Last-Translator: Liudas Ališauskas \n" +"Language-Team: Lithuanian \n" +"Language: lt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n%10>=2 && (n%100<10 || n" +"%100>=20) ? 1 : n%10==0 || (n%100>10 && n%100<20) ? 2 : 3);\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Liudas Ališauskas" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "liudas@akmc.lt" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su tarnyba" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Tarnyba, kurią naudoja „kdesu“" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autorius" diff --git a/po/ml/kdesud5.po b/po/ml/kdesud5.po new file mode 100644 index 0000000..02bab39 --- /dev/null +++ b/po/ml/kdesud5.po @@ -0,0 +1,54 @@ +# Malayalam translations for kdesu package. +# Copyright (C) 2019 This file is copyright: +# This file is distributed under the same license as the kdesu package. +# Automatically generated, 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: kdesu\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2019-12-12 21:01+0000\n" +"Last-Translator: Vivek KJ Pazhedath \n" +"Language-Team: Swathanthra|സ്വതന്ത്ര Malayalam|മലയാളം Computing|കമ്പ്യൂട്ടിങ്ങ് \n" +"Language: ml\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "shijualexonline@gmail.com,snalledam@dataone.in,vivekkj2004@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "" diff --git a/po/nb/kdesud5.po b/po/nb/kdesud5.po new file mode 100644 index 0000000..05aa367 --- /dev/null +++ b/po/nb/kdesud5.po @@ -0,0 +1,55 @@ +# Translation of kdesud5 to Norwegian Bokmål +# +# Hans Petter Bieker , 2000. +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2007-09-20 21:25+0200\n" +"Last-Translator: MagicPO 0.3 (automated)\n" +"Language-Team: Norwegian Bokmål \n" +"Language: nb\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: MagicPO 0.3\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Environment: kde\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Christian A. Strømmen" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "number1@realityx.net" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su-daemon" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Daemon brukt av kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright © 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Forfatter" diff --git a/po/nds/kdesud5.po b/po/nds/kdesud5.po new file mode 100644 index 0000000..4b343cb --- /dev/null +++ b/po/nds/kdesud5.po @@ -0,0 +1,56 @@ +# Translation of kdesud.po to Low Saxon +# Copyright (C) 2004, 2006, 2007, 2008 Free Software Foundation, Inc. +# Heiko Evermann , 2004. +# Volker Jockheck , 2004. +# Sönke Dibbern , 2006, 2007, 2008. +# Manfred Wiese , 2010, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2011-06-22 05:49+0200\n" +"Last-Translator: Manfred Wiese \n" +"Language-Team: Low Saxon \n" +"Language: nds\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.0\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Sönke Dibbern" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "s_dibbern@web.de" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "su-Dämoon vun KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Vun \"kdesu\" bruukt Dämoon" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright © 1999, 2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/nl/kdesud5.po b/po/nl/kdesud5.po new file mode 100644 index 0000000..68360e1 --- /dev/null +++ b/po/nl/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Freek de Kruijf , 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-03-29 10:11+0100\n" +"Last-Translator: Freek de Kruijf \n" +"Language-Team: Dutch \n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Freek de Kruijf" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "freekdekruijf@kde.nl" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su-daemon" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Daemon gebruikt door kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Auteur" diff --git a/po/nn/kdesud5.po b/po/nn/kdesud5.po new file mode 100644 index 0000000..8b2ebb2 --- /dev/null +++ b/po/nn/kdesud5.po @@ -0,0 +1,56 @@ +# Translation of kdesud5 to Norwegian Nynorsk +# +# Gaute Hvoslef Kvalnes , 2000. +# Karl Ove Hufthammer , 2007, 2008. +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2008-08-03 19:20+0200\n" +"Last-Translator: Karl Ove Hufthammer \n" +"Language-Team: Norwegian Nynorsk \n" +"Language: nn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.11.4\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Environment: kde\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Gaute Hvoslef Kvalnes" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "gaute@verdsveven.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su-demon" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Demonen kdesu brukar" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright © 1999–2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Opphavsperson" diff --git a/po/pa/kdesud5.po b/po/pa/kdesud5.po new file mode 100644 index 0000000..ced3e1f --- /dev/null +++ b/po/pa/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# A S Alam , 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-07-08 14:28-0500\n" +"Last-Translator: A S Alam \n" +"Language-Team: Punjabi/Panjabi \n" +"Language: pa\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "ਅਮਨਪਰੀਤ ਸਿੰਘ ਆਲਮ (A S Alam)" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "aalam@users.sf.net" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su ਡੈਮਨ" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "kdesu ਰਾਹੀਂ ਵਰਤੀ ਜਾਂਦੀ ਡੈਮਨ" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "ਗਰੀਟ ਜਾਨਸਨ" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "ਲੇਖਕ" diff --git a/po/pl/kdesud5.po b/po/pl/kdesud5.po new file mode 100644 index 0000000..60cd024 --- /dev/null +++ b/po/pl/kdesud5.po @@ -0,0 +1,54 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Łukasz Wojniłowicz , 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-03-29 07:15+0100\n" +"Last-Translator: Łukasz Wojniłowicz \n" +"Language-Team: Polish \n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Łukasz Wojniłowicz" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "lukasz.wojnilowicz@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Usługa su dla KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Usługa używana przez kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/pt/kdesud5.po b/po/pt/kdesud5.po new file mode 100644 index 0000000..cf7ecf4 --- /dev/null +++ b/po/pt/kdesud5.po @@ -0,0 +1,49 @@ +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-03-29 12:14+0000\n" +"Last-Translator: José Nuno Coelho Pires \n" +"Language-Team: Portuguese \n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-POFile-SpellExtra: Jansen Geert su kdesu\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "José Nuno Pires" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "zepires@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Servidor do 'su' do KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "O servidor usado pelo kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autoria" diff --git a/po/pt_BR/kdesud5.po b/po/pt_BR/kdesud5.po new file mode 100644 index 0000000..a89d880 --- /dev/null +++ b/po/pt_BR/kdesud5.po @@ -0,0 +1,54 @@ +# Translation of kdesud5.po to Brazilian Portuguese +# Copyright (C) 2014 This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# André Marcelo Alvarenga , 2014. +msgid "" +msgstr "" +"Project-Id-Version: kdesud5\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-03-31 23:30-0300\n" +"Last-Translator: André Marcelo Alvarenga \n" +"Language-Team: Brazilian Portuguese \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "André Marcelo Alvarenga" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "alvarenga@kde.org" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Serviço su do KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Serviço utilizado pelo kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/ro/kdesud5.po b/po/ro/kdesud5.po new file mode 100644 index 0000000..1c10ff0 --- /dev/null +++ b/po/ro/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# Sergiu Bivol , 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-08-16 14:50+0300\n" +"Last-Translator: Sergiu Bivol \n" +"Language-Team: Romanian \n" +"Language: ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " +"20)) ? 1 : 2;\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Sergiu Bivol" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "sergiu@cip.md" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Demon KDE pentru „su”" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Demon utilizat de kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Drept de autor (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Autor" diff --git a/po/ru/kdesud5.po b/po/ru/kdesud5.po new file mode 100644 index 0000000..416bb97 --- /dev/null +++ b/po/ru/kdesud5.po @@ -0,0 +1,59 @@ +# KDE2 kdesud.pot Russian translation +# Copyright (C) 2000, KDE Team. +# +# Igor Azarniy , 2000. +# Andrey Cherepanov , 2009. +# Alexander Potashev , 2014. +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-06-25 04:02+0400\n" +"Last-Translator: Alexander Potashev \n" +"Language-Team: Russian \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.5\n" +"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n" +"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Environment: kde\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Igor Azarniy, Николай Шафоростов, Александр Поташев" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "azarniy@usa.net, shaforostoff@kde.ru, aspotashev@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Служба KDE su" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Служба, используемая kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "© Geert Jansen, 1999, 2000" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Автор" diff --git a/po/se/kdesud5.po b/po/se/kdesud5.po new file mode 100644 index 0000000..60efc9e --- /dev/null +++ b/po/se/kdesud5.po @@ -0,0 +1,55 @@ +# Translation of kdesud5 to Northern Sami +# +# Børre Gaup , 2002, 2003, 2007. +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2007-12-10 05:00+0100\n" +"Last-Translator: Børre Gaup \n" +"Language-Team: Northern Sami \n" +"Language: se\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.11.4\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Environment: kde\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Børre Gaup" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "boerre@skolelinux.no" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su daemon" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Deamona maid kdesu geavaha" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright © 1999–2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Čálli" diff --git a/po/sk/kdesud5.po b/po/sk/kdesud5.po new file mode 100644 index 0000000..11c2300 --- /dev/null +++ b/po/sk/kdesud5.po @@ -0,0 +1,51 @@ +# translation of kdesud.po to Slovak +# Roman Paholik , 2014. +msgid "" +msgstr "" +"Project-Id-Version: kdesud\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2021-11-17 19:38+0100\n" +"Last-Translator: Dušan Kazik \n" +"Language-Team: Slovak \n" +"Language: sk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.0\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Roman Paholík,Dušan Kazik" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "wizzardsk@gmail.com,prescott66@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Démon KDE su" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Démon používaný nástrojom kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Autorské práva (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Tvorca" diff --git a/po/sl/kdesud5.po b/po/sl/kdesud5.po new file mode 100644 index 0000000..e0e3df2 --- /dev/null +++ b/po/sl/kdesud5.po @@ -0,0 +1,54 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Andrej Mernik , 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-06-12 14:47+0200\n" +"Last-Translator: Andrej Mernik \n" +"Language-Team: Slovenian \n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n" +"%100==4 ? 3 : 0);\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Andrej Mernik" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "andrejm@ubuntu.si" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Ozadnji program su za KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Ozadnji program, ki ga uporablja kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Avtorske pravice © 1999, 2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Avtor" diff --git a/po/sr/kdesud5.po b/po/sr/kdesud5.po new file mode 100644 index 0000000..6817ec2 --- /dev/null +++ b/po/sr/kdesud5.po @@ -0,0 +1,56 @@ +# Translation of kdesud5.po into Serbian. +# Marko Rosic , 2000. +# Toplica Tanaskovic , 2003. +# Chusslove Illich , 2007, 2017. +msgid "" +msgstr "" +"Project-Id-Version: kdesud5\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-05-20 02:55+0200\n" +"PO-Revision-Date: 2017-09-28 17:57+0200\n" +"Last-Translator: Chusslove Illich \n" +"Language-Team: Serbian \n" +"Language: sr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n" +"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" +"X-Environment: kde\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Часлав Илић" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "caslav.ilic@gmx.net" + +#: kdesud.cpp:274 +#, kde-format +msgid "KDE su daemon" +msgstr "КДЕ‑ов демон за su" + +#: kdesud.cpp:275 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Демон КДЕ суа" + +#: kdesud.cpp:277 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "© 1999-2000, Герт Јансен" + +#: kdesud.cpp:278 +#, kde-format +msgid "Geert Jansen" +msgstr "Герт Јансен" + +#: kdesud.cpp:278 +#, kde-format +msgid "Author" +msgstr "аутор" diff --git a/po/sr@ijekavian/kdesud5.po b/po/sr@ijekavian/kdesud5.po new file mode 100644 index 0000000..ec0ba06 --- /dev/null +++ b/po/sr@ijekavian/kdesud5.po @@ -0,0 +1,56 @@ +# Translation of kdesud5.po into Serbian. +# Marko Rosic , 2000. +# Toplica Tanaskovic , 2003. +# Chusslove Illich , 2007, 2017. +msgid "" +msgstr "" +"Project-Id-Version: kdesud5\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-05-20 02:55+0200\n" +"PO-Revision-Date: 2017-09-28 17:57+0200\n" +"Last-Translator: Chusslove Illich \n" +"Language-Team: Serbian \n" +"Language: sr@ijekavian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n" +"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" +"X-Environment: kde\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Часлав Илић" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "caslav.ilic@gmx.net" + +#: kdesud.cpp:274 +#, kde-format +msgid "KDE su daemon" +msgstr "КДЕ‑ов демон за su" + +#: kdesud.cpp:275 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Демон КДЕ суа" + +#: kdesud.cpp:277 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "© 1999-2000, Герт Јансен" + +#: kdesud.cpp:278 +#, kde-format +msgid "Geert Jansen" +msgstr "Герт Јансен" + +#: kdesud.cpp:278 +#, kde-format +msgid "Author" +msgstr "аутор" diff --git a/po/sr@ijekavianlatin/kdesud5.po b/po/sr@ijekavianlatin/kdesud5.po new file mode 100644 index 0000000..13816ee --- /dev/null +++ b/po/sr@ijekavianlatin/kdesud5.po @@ -0,0 +1,56 @@ +# Translation of kdesud5.po into Serbian. +# Marko Rosic , 2000. +# Toplica Tanaskovic , 2003. +# Chusslove Illich , 2007, 2017. +msgid "" +msgstr "" +"Project-Id-Version: kdesud5\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-05-20 02:55+0200\n" +"PO-Revision-Date: 2017-09-28 17:57+0200\n" +"Last-Translator: Chusslove Illich \n" +"Language-Team: Serbian \n" +"Language: sr@ijekavianlatin\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n" +"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" +"X-Environment: kde\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Časlav Ilić" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "caslav.ilic@gmx.net" + +#: kdesud.cpp:274 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE‑ov demon za su" + +#: kdesud.cpp:275 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Demon KDE sua" + +#: kdesud.cpp:277 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "© 1999-2000, Gert Jansen" + +#: kdesud.cpp:278 +#, kde-format +msgid "Geert Jansen" +msgstr "Gert Jansen" + +#: kdesud.cpp:278 +#, kde-format +msgid "Author" +msgstr "autor" diff --git a/po/sr@latin/kdesud5.po b/po/sr@latin/kdesud5.po new file mode 100644 index 0000000..2c1e45a --- /dev/null +++ b/po/sr@latin/kdesud5.po @@ -0,0 +1,56 @@ +# Translation of kdesud5.po into Serbian. +# Marko Rosic , 2000. +# Toplica Tanaskovic , 2003. +# Chusslove Illich , 2007, 2017. +msgid "" +msgstr "" +"Project-Id-Version: kdesud5\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-05-20 02:55+0200\n" +"PO-Revision-Date: 2017-09-28 17:57+0200\n" +"Last-Translator: Chusslove Illich \n" +"Language-Team: Serbian \n" +"Language: sr@latin\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n" +"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" +"X-Environment: kde\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Časlav Ilić" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "caslav.ilic@gmx.net" + +#: kdesud.cpp:274 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE‑ov demon za su" + +#: kdesud.cpp:275 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Demon KDE sua" + +#: kdesud.cpp:277 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "© 1999-2000, Gert Jansen" + +#: kdesud.cpp:278 +#, kde-format +msgid "Geert Jansen" +msgstr "Gert Jansen" + +#: kdesud.cpp:278 +#, kde-format +msgid "Author" +msgstr "autor" diff --git a/po/sv/kdesud5.po b/po/sv/kdesud5.po new file mode 100644 index 0000000..ef4e548 --- /dev/null +++ b/po/sv/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Stefan Asserhäll , 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-04-01 21:06+0200\n" +"Last-Translator: Stefan Asserhäll \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.4\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Stefan Asserhäll" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "stefan.asserhall@bredband.net" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE-demon för administratörsläge" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Demon som används av kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright © 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Upphovsman" diff --git a/po/tg/kdesud5.po b/po/tg/kdesud5.po new file mode 100644 index 0000000..efc3273 --- /dev/null +++ b/po/tg/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdesu package. +# +# Victor Ibragimov , 2019. +msgid "" +msgstr "" +"Project-Id-Version: kdesu\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2019-08-16 19:20+0500\n" +"Last-Translator: Victor Ibragimov \n" +"Language-Team: English \n" +"Language: tg\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 19.04.3\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Victor Ibragimov" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "victor.ibragimov@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Раванди дохилии KDE su" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Раванди дохилие, ки бо kdesu истифода мешавад" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Ҳуқуқи муаллиф (c) 1999, 2000 Гирт Ҷансен (Geert Jansen)" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Гирт Ҷансен (Geert Jansen)" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Муаллиф" diff --git a/po/tr/kdesud5.po b/po/tr/kdesud5.po new file mode 100644 index 0000000..cfe370a --- /dev/null +++ b/po/tr/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Volkan Gezer , 2015. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2015-02-08 12:35+0100\n" +"Last-Translator: Volkan Gezer \n" +"Language-Team: Turkish \n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Volkan Gezer" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "volkangezer@gmail.com" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su aracı" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Kdesu tarafından kullanılan araç" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Telif Hakkı (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Yazar" diff --git a/po/uk/kdesud5.po b/po/uk/kdesud5.po new file mode 100644 index 0000000..48ca3b9 --- /dev/null +++ b/po/uk/kdesud5.po @@ -0,0 +1,56 @@ +# Translation of kdesud5.po to Ukrainian +# Copyright (C) 2018 This_file_is_part_of_KDE +# This file is distributed under the license LGPL version 2.1 or +# version 3 or later versions approved by the membership of KDE e.V. +# +# Yuri Chornoivan , 2014. +msgid "" +msgstr "" +"Project-Id-Version: kdesud5\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-03-29 07:52+0200\n" +"Last-Translator: Yuri Chornoivan \n" +"Language-Team: Ukrainian \n" +"Language: uk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n" +"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Andriy Rysin" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "rysin@kde.org" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "Фонова служба su для KDE" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "Фонова служба, що використовується для kdesu" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "© Geert Jansen, 1999, 2000" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "Автор" diff --git a/po/zh_CN/kdesud5.po b/po/zh_CN/kdesud5.po new file mode 100644 index 0000000..63cf072 --- /dev/null +++ b/po/zh_CN/kdesud5.po @@ -0,0 +1,57 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Weng Xuetian , 2014. +msgid "" +msgstr "" +"Project-Id-Version: kdeorg\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2022-02-26 05:16\n" +"Last-Translator: \n" +"Language-Team: Chinese Simplified\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Crowdin-Project: kdeorg\n" +"X-Crowdin-Project-ID: 269464\n" +"X-Crowdin-Language: zh-CN\n" +"X-Crowdin-File: /kf5-trunk/messages/kdesu/kdesud5.pot\n" +"X-Crowdin-File-ID: 5568\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "KDE 中国" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "kde-china@kde.org" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su 守护程序" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "kdesu 所使用的守护程序" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "作者" diff --git a/po/zh_TW/kdesud5.po b/po/zh_TW/kdesud5.po new file mode 100644 index 0000000..31cefb1 --- /dev/null +++ b/po/zh_TW/kdesud5.po @@ -0,0 +1,53 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Franklin Weng , 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2022-02-01 00:40+0000\n" +"PO-Revision-Date: 2014-04-22 10:30+0800\n" +"Last-Translator: Franklin Weng \n" +"Language-Team: Chinese Traditional \n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "Franklin Weng" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "franklin@nospam.goodhorse.idv.tw" + +#: kdesud.cpp:322 +#, kde-format +msgid "KDE su daemon" +msgstr "KDE su 伺服程式" + +#: kdesud.cpp:324 +#, kde-format +msgid "Daemon used by kdesu" +msgstr "kdesu 使用的伺服程式" + +#: kdesud.cpp:326 +#, kde-format +msgid "Copyright (c) 1999,2000 Geert Jansen" +msgstr "Copyright (c) 1999,2000 Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Geert Jansen" +msgstr "Geert Jansen" + +#: kdesud.cpp:327 +#, kde-format +msgid "Author" +msgstr "作者" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..f94b591 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,146 @@ +add_subdirectory(kdesud) + +include(CheckTypeSize) +include(CheckIncludeFiles) +include(CheckFunctionExists) + +check_function_exists(setpriority HAVE_SETPRIORITY) +check_function_exists(getpeereid HAVE_GETPEEREID) +check_function_exists(initgroups HAVE_INITGROUPS) + +check_include_files(sys/select.h HAVE_SYS_SELECT_H) + +set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) +check_type_size("struct ucred" STRUCT_UCRED) #defines HAVE_STRUCT_UCRED (bool) and STRUCT_UCRED (size, unused) +set(CMAKE_EXTRA_INCLUDE_FILES) #reset CMAKE_EXTRA_INCLUDE_FILES + +configure_file(config-kdesu.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kdesu.h) + +add_library(KF5Su) +add_library(KF5::Su ALIAS KF5Su) + +set_target_properties(KF5Su PROPERTIES + VERSION ${KDESU_VERSION} + SOVERSION ${KDESU_SOVERSION} + EXPORT_NAME Su +) + +target_sources(KF5Su PRIVATE + client.cpp + ptyprocess.cpp + kcookie.cpp + suprocess.cpp + sshprocess.cpp + stubprocess.cpp +) + +ecm_qt_declare_logging_category(KF5Su + HEADER ksu_debug.h + IDENTIFIER KSU_LOG + CATEGORY_NAME kf.su + DESCRIPTION "KSu (KDESu)" + EXPORT KSU +) + +ecm_generate_export_header(KF5Su + EXPORT_FILE_NAME kdesu/kdesu_export.h + BASE_NAME KDESu + GROUP_BASE_NAME KF + VERSION ${KF_VERSION} + DEPRECATED_BASE_VERSION 0 + DEPRECATION_VERSIONS 5.0 + EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} +) + +if(KDESU_USE_SUDO_DEFAULT) + target_compile_definitions(KF5Su PRIVATE -DKDESU_USE_SUDO_DEFAULT="true") +elseif(KDESU_USE_DOAS_DEFAULT) + target_compile_definitions(KF5Su PRIVATE -DKDESU_USE_DOAS_DEFAULT="true") +endif() + +target_include_directories(KF5Su PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..) + +# Apps must include or +target_include_directories(KF5Su INTERFACE "$") + +target_link_libraries(KF5Su + PUBLIC + KF5::Pty + PRIVATE + KF5::CoreAddons # KUser::loginName + KF5::ConfigCore # KConfigGroup +) + + +ecm_generate_headers(KDESu_CamelCase_HEADERS + HEADER_NAMES + PtyProcess + SuProcess + SshProcess + StubProcess + Client # technically the class is called KDEsuClient... + + PREFIX KDESu + REQUIRED_HEADERS KDESu_HEADERS +) +install(FILES ${KDESu_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KDESu/KDESu COMPONENT Devel) + +install(TARGETS KF5Su EXPORT KF5SuTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) + +########### next target ############### + +include(ECMMarkNonGuiExecutable) + +set_source_files_properties(kdesu_stub.c PROPERTIES + COMPILE_DEFINITIONS "_XOPEN_SOURCE;_BSD_SOURCE") +add_executable(kdesu_stub kdesu_stub.c) +ecm_mark_nongui_executable(kdesu_stub) + +install(TARGETS kdesu_stub DESTINATION ${KDE_INSTALL_LIBEXECDIR_KF}) + +########### install files ############### +install(FILES + su.h + ssh.h + stub.h + process.h + defaults.h + ${CMAKE_CURRENT_BINARY_DIR}/kdesu/kdesu_export.h + ${KDESu_HEADERS} + DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KDESu/kdesu COMPONENT Devel +) + +if(BUILD_QCH) + ecm_add_qch( + KF5Su_QCH + NAME KDESu + BASE_NAME KF5Su + VERSION ${KF_VERSION} + ORG_DOMAIN org.kde + SOURCES # using only public headers, to cover only public API + ${KDESu_HEADERS} + MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md" + LINK_QCHS + KF5Pty_QCH + INCLUDE_DIRS + ${CMAKE_CURRENT_BINARY_DIR} + BLANK_MACROS + KDESU_EXPORT + KDESU_DEPRECATED + KDESU_DEPRECATED_EXPORT + "KDESU_DEPRECATED_VERSION(x, y, t)" + TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} + QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} + COMPONENT Devel + ) +endif() + +include(ECMGeneratePriFile) +ecm_generate_pri_file(BASE_NAME KDESu LIB_NAME KF5Su DEPS "KPty" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF}/KDESu) +install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) + +ecm_qt_install_logging_categories( + EXPORT KSU + FILE ksu.categories + DESTINATION "${KDE_INSTALL_LOGGINGCATEGORIESDIR}" +) diff --git a/src/README b/src/README new file mode 100644 index 0000000..0a6acd9 --- /dev/null +++ b/src/README @@ -0,0 +1,13 @@ +Maintainer: Adriaan de Groot +Maintainer: kdesu was maintained by Alan Eldridge until his + death in 2003. + +README for libkdesu. + +Libkdesu provides functionality for building GUI front ends for +(password asking) console mode programs. For example, kdesu and +kdessh use it to interface with su and ssh respectively. + +libkdesu is Copyright (c) 1999,2000 Geert Jansen + +Distributed under the GNU Library General Public License, version 2. diff --git a/src/client.cpp b/src/client.cpp new file mode 100644 index 0000000..c9f9b6a --- /dev/null +++ b/src/client.cpp @@ -0,0 +1,438 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + SPDX-License-Identifier: GPL-2.0-only + + client.cpp: A client for kdesud. +*/ + +#include "client.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +extern int kdesuDebugArea(); + +namespace KDESu +{ +class KDEsuClientPrivate +{ +public: + KDEsuClientPrivate() + : sockfd(-1) + { + } + QString daemon; + int sockfd; + QByteArray sock; +}; + +#ifndef SUN_LEN +#define SUN_LEN(ptr) ((QT_SOCKLEN_T)(((struct sockaddr_un *)0)->sun_path) + strlen((ptr)->sun_path)) +#endif + +KDEsuClient::KDEsuClient() + : d(new KDEsuClientPrivate) +{ +#if HAVE_X11 + QString display = QString::fromLocal8Bit(qgetenv("DISPLAY")); + if (display.isEmpty()) { + // we might be on Wayland + display = QString::fromLocal8Bit(qgetenv("WAYLAND_DISPLAY")); + } + if (display.isEmpty()) { + qCWarning(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "$DISPLAY is not set."; + return; + } + + // strip the screen number from the display + display.remove(QRegularExpression(QStringLiteral("\\.[0-9]+$"))); +#else + QString display = QStringLiteral("NODISPLAY"); +#endif + + d->sock = QFile::encodeName(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) + QStringLiteral("/kdesud_") + display); + connect(); +} + +KDEsuClient::~KDEsuClient() +{ + if (d->sockfd >= 0) { + close(d->sockfd); + } +} + +int KDEsuClient::connect() +{ + if (d->sockfd >= 0) { + close(d->sockfd); + } + if (access(d->sock.constData(), R_OK | W_OK)) { + d->sockfd = -1; + return -1; + } + + d->sockfd = socket(PF_UNIX, SOCK_STREAM, 0); + if (d->sockfd < 0) { + qCWarning(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "socket():" << strerror(errno); + return -1; + } + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, d->sock.constData()); + + if (QT_SOCKET_CONNECT(d->sockfd, (struct sockaddr *)&addr, SUN_LEN(&addr)) < 0) { + qCWarning(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "connect():" << strerror(errno); + close(d->sockfd); + d->sockfd = -1; + return -1; + } + +#if !defined(SO_PEERCRED) || !HAVE_STRUCT_UCRED +#if HAVE_GETPEEREID + uid_t euid; + gid_t egid; + // Security: if socket exists, we must own it + if (getpeereid(d->sockfd, &euid, &egid) == 0 && euid != getuid()) { + qCWarning(KSU_LOG) << "socket not owned by me! socket uid =" << euid; + close(d->sockfd); + d->sockfd = -1; + return -1; + } +#else +#ifdef __GNUC__ +#warning "Using sloppy security checks" +#endif + // We check the owner of the socket after we have connected. + // If the socket was somehow not ours an attacker will be able + // to delete it after we connect but shouldn't be able to + // create a socket that is owned by us. + QT_STATBUF s; + if (QT_LSTAT(d->sock.constData(), &s) != 0) { + qCWarning(KSU_LOG) << "stat failed (" << d->sock << ")"; + close(d->sockfd); + d->sockfd = -1; + return -1; + } + if (s.st_uid != getuid()) { + qCWarning(KSU_LOG) << "socket not owned by me! socket uid =" << s.st_uid; + close(d->sockfd); + d->sockfd = -1; + return -1; + } + if (!S_ISSOCK(s.st_mode)) { + qCWarning(KSU_LOG) << "socket is not a socket (" << d->sock << ")"; + close(d->sockfd); + d->sockfd = -1; + return -1; + } +#endif +#else + struct ucred cred; + QT_SOCKLEN_T siz = sizeof(cred); + + // Security: if socket exists, we must own it + if (getsockopt(d->sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &siz) == 0 && cred.uid != getuid()) { + qCWarning(KSU_LOG) << "socket not owned by me! socket uid =" << cred.uid; + close(d->sockfd); + d->sockfd = -1; + return -1; + } +#endif + + return 0; +} + +QByteArray KDEsuClient::escape(const QByteArray &str) +{ + QByteArray copy; + copy.reserve(str.size() + 4); + copy.append('"'); + for (const uchar c : str) { + if (c < 32) { + copy.append('\\'); + copy.append('^'); + copy.append(c + '@'); + } else { + if (c == '\\' || c == '"') { + copy.append('\\'); + } + copy.append(c); + } + } + copy.append('"'); + return copy; +} + +int KDEsuClient::command(const QByteArray &cmd, QByteArray *result) +{ + if (d->sockfd < 0) { + return -1; + } + + if (send(d->sockfd, cmd.constData(), cmd.length(), 0) != (int)cmd.length()) { + return -1; + } + + char buf[1024]; + int nbytes = recv(d->sockfd, buf, 1023, 0); + if (nbytes <= 0) { + qCWarning(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "no reply from daemon."; + return -1; + } + buf[nbytes] = '\000'; + + QByteArray reply = buf; + if (reply.left(2) != "OK") { + return -1; + } + + if (result) { + *result = reply.mid(3, reply.length() - 4); + } + return 0; +} + +int KDEsuClient::setPass(const char *pass, int timeout) +{ + QByteArray cmd = "PASS "; + cmd += escape(pass); + cmd += ' '; + cmd += QByteArray().setNum(timeout); + cmd += '\n'; + return command(cmd); +} + +int KDEsuClient::exec(const QByteArray &prog, const QByteArray &user, const QByteArray &options, const QList &env) +{ + QByteArray cmd; + cmd = "EXEC "; + cmd += escape(prog); + cmd += ' '; + cmd += escape(user); + if (!options.isEmpty() || !env.isEmpty()) { + cmd += ' '; + cmd += escape(options); + for (const auto &var : env) { + cmd += ' '; + cmd += escape(var); + } + } + cmd += '\n'; + return command(cmd); +} + +int KDEsuClient::setHost(const QByteArray &host) +{ + QByteArray cmd = "HOST "; + cmd += escape(host); + cmd += '\n'; + return command(cmd); +} + +int KDEsuClient::setPriority(int prio) +{ + QByteArray cmd; + cmd += "PRIO "; + cmd += QByteArray::number(prio); + cmd += '\n'; + return command(cmd); +} + +int KDEsuClient::setScheduler(int sched) +{ + QByteArray cmd; + cmd += "SCHD "; + cmd += QByteArray::number(sched); + cmd += '\n'; + return command(cmd); +} + +int KDEsuClient::delCommand(const QByteArray &key, const QByteArray &user) +{ + QByteArray cmd = "DEL "; + cmd += escape(key); + cmd += ' '; + cmd += escape(user); + cmd += '\n'; + return command(cmd); +} +int KDEsuClient::setVar(const QByteArray &key, const QByteArray &value, int timeout, const QByteArray &group) +{ + QByteArray cmd = "SET "; + cmd += escape(key); + cmd += ' '; + cmd += escape(value); + cmd += ' '; + cmd += escape(group); + cmd += ' '; + cmd += QByteArray().setNum(timeout); + cmd += '\n'; + return command(cmd); +} + +QByteArray KDEsuClient::getVar(const QByteArray &key) +{ + QByteArray cmd = "GET "; + cmd += escape(key); + cmd += '\n'; + QByteArray reply; + command(cmd, &reply); + return reply; +} + +QList KDEsuClient::getKeys(const QByteArray &group) +{ + QByteArray cmd = "GETK "; + cmd += escape(group); + cmd += '\n'; + QByteArray reply; + command(cmd, &reply); + int index = 0; + int pos; + QList list; + if (!reply.isEmpty()) { + while (1) { + pos = reply.indexOf('\007', index); + if (pos == -1) { + if (index == 0) { + list.append(reply); + } else { + list.append(reply.mid(index)); + } + break; + } else { + list.append(reply.mid(index, pos - index)); + } + index = pos + 1; + } + } + return list; +} + +bool KDEsuClient::findGroup(const QByteArray &group) +{ + QByteArray cmd = "CHKG "; + cmd += escape(group); + cmd += '\n'; + if (command(cmd) == -1) { + return false; + } + return true; +} + +int KDEsuClient::delVar(const QByteArray &key) +{ + QByteArray cmd = "DELV "; + cmd += escape(key); + cmd += '\n'; + return command(cmd); +} + +int KDEsuClient::delGroup(const QByteArray &group) +{ + QByteArray cmd = "DELG "; + cmd += escape(group); + cmd += '\n'; + return command(cmd); +} + +int KDEsuClient::delVars(const QByteArray &special_key) +{ + QByteArray cmd = "DELS "; + cmd += escape(special_key); + cmd += '\n'; + return command(cmd); +} + +int KDEsuClient::ping() +{ + return command("PING\n"); +} + +int KDEsuClient::exitCode() +{ + QByteArray result; + if (command("EXIT\n", &result) != 0) { + return -1; + } + + return result.toInt(); +} + +int KDEsuClient::stopServer() +{ + return command("STOP\n"); +} + +static QString findDaemon() +{ + QString daemon = QFile::decodeName(KDE_INSTALL_FULL_LIBEXECDIR_KF "/kdesud"); + if (!QFile::exists(daemon)) { // if not in libexec, find it in PATH + daemon = QStandardPaths::findExecutable(QStringLiteral("kdesud")); + if (daemon.isEmpty()) { + qCWarning(KSU_LOG) << "kdesud daemon not found."; + } + } + return daemon; +} + +bool KDEsuClient::isServerSGID() +{ + if (d->daemon.isEmpty()) { + d->daemon = findDaemon(); + } + if (d->daemon.isEmpty()) { + return false; + } + + QT_STATBUF sbuf; + if (QT_STAT(QFile::encodeName(d->daemon).constData(), &sbuf) < 0) { + qCWarning(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "stat():" << strerror(errno); + return false; + } + return (sbuf.st_mode & S_ISGID); +} + +int KDEsuClient::startServer() +{ + if (d->daemon.isEmpty()) { + d->daemon = findDaemon(); + } + if (d->daemon.isEmpty()) { + return -1; + } + + if (!isServerSGID()) { + qCWarning(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "kdesud not setgid!"; + } + + QProcess proc; + proc.start(d->daemon, QStringList{}); + if (!proc.waitForFinished()) { + qCCritical(KSU_LOG) << "Couldn't start kdesud!"; + return -1; + } + + connect(); + return proc.exitCode(); +} + +} // namespace KDESu diff --git a/src/client.h b/src/client.h new file mode 100644 index 0000000..baf9974 --- /dev/null +++ b/src/client.h @@ -0,0 +1,201 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + SPDX-License-Identifier: GPL-2.0-only + + client.h: client to access kdesud. +*/ + +#ifndef KDESUCLIENT_H +#define KDESUCLIENT_H + +#include + +#include +#include +#include + +#ifdef Q_OS_UNIX + +namespace KDESu +{ +/** \class KDEsuClient client.h KDESu/Client + * A client class to access kdesud, the KDE su daemon. Kdesud can assist in + * password caching in two ways: + * + * @li For high security passwords, like for su and ssh, it executes the + * password requesting command for you. It feeds the password to the + * command, without ever returning it to you, the user. The daemon should + * be installed setgid nogroup, in order to be able to act as an inaccessible, + * trusted 3rd party. + * See exec, setPass, delCommand. + * + * @li For lower security passwords, like web and ftp passwords, it can act + * as a persistent storage for string variables. These variables are + * returned to the user, and the daemon doesn't need to be setgid nogroup + * for this. + * See setVar, delVar, delGroup. + */ + +class KDESU_EXPORT KDEsuClient +{ +public: + KDEsuClient(); + ~KDEsuClient(); + + KDEsuClient(const KDEsuClient &) = delete; + KDEsuClient &operator=(const KDEsuClient &) = delete; + + /** + * Lets kdesud execute a command. If the daemon does not have a password + * for this command, this will fail and you need to call setPass(). + * + * @param command The command to execute. + * @param user The user to run the command as. + * @param options Extra options. + * @param env Extra environment variables. + * @return Zero on success, -1 on failure. + */ + int exec(const QByteArray &command, const QByteArray &user, const QByteArray &options = nullptr, const QList &env = QList()); + + /** + * Wait for the last command to exit and return the exit code. + * @return Exit code of last command, -1 on failure. + */ + int exitCode(); + + /** + * Set root's password, lasts one session. + * + * @param pass Root's password. + * @param timeout The time that a password will live. + * @return Zero on success, -1 on failure. + */ + int setPass(const char *pass, int timeout); + + /** + * Set the target host (optional). + */ + int setHost(const QByteArray &host); + + /** + * Set the desired priority (optional), see StubProcess. + */ + int setPriority(int priority); + + /** + * Set the desired scheduler (optional), see StubProcess. + */ + int setScheduler(int scheduler); + + /** + * Remove a password for a user/command. + * @param command The command. + * @param user The user. + * @return zero on success, -1 on an error + */ + int delCommand(const QByteArray &command, const QByteArray &user); + + /** + * Set a persistent variable. + * @param key The name of the variable. + * @param value Its value. + * @param timeout The timeout in seconds for this key. Zero means + * no timeout. + * @param group Make the key part of a group. See delGroup. + * @return zero on success, -1 on failure. + */ + int setVar(const QByteArray &key, const QByteArray &value, int timeout = 0, const QByteArray &group = nullptr); + + /** + * Get a persistent variable. + * @param key The name of the variable. + * @return Its value. + */ + QByteArray getVar(const QByteArray &key); + + /** + * Gets all the keys that are membes of the given group. + * @param group the group name of the variables. + * @return a list of the keys in the group. + */ + QList getKeys(const QByteArray &group); + + /** + * Returns true if the specified group exists is + * cached. + * + * @param group the group key + * @return true if the group is found + */ + bool findGroup(const QByteArray &group); + + /** + * Delete a persistent variable. + * @param key The name of the variable. + * @return zero on success, -1 on failure. + */ + int delVar(const QByteArray &key); + + /** + * Delete all persistent variables with the given key. + * + * A specicalized variant of delVar(QByteArray) that removes all + * subsets of the cached variables given by @p key. In order for all + * cached variables related to this key to be deleted properly, the + * value given to the @p group argument when the setVar function + * was called, must be a subset of the argument given here and the key + * + * @note Simply supplying the group key here WILL not necessarily + * work. If you only have a group key, then use delGroup instead. + * + * @param special_key the name of the variable. + * @return zero on success, -1 on failure. + */ + int delVars(const QByteArray &special_key); + + /** + * Delete all persistent variables in a group. + * + * @param group the group name. See setVar. + * @return + */ + int delGroup(const QByteArray &group); + + /** + * Ping kdesud. This can be used for diagnostics. + * @return Zero on success, -1 on failure + */ + int ping(); + + /** + * Stop the daemon. + */ + int stopServer(); + + /** + * Try to start up kdesud + */ + int startServer(); + + /** + * Returns true if the server is safe (installed setgid), false otherwise. + */ + bool isServerSGID(); + +private: + int connect(); + + int command(const QByteArray &cmd, QByteArray *result = nullptr); + QByteArray escape(const QByteArray &str); + +private: + std::unique_ptr const d; +}; + +} // END namespace KDESu + +#endif // Q_OS_UNIX + +#endif // KDESUCLIENT_H diff --git a/src/config-kdesu.h.cmake b/src/config-kdesu.h.cmake new file mode 100644 index 0000000..c7e111c --- /dev/null +++ b/src/config-kdesu.h.cmake @@ -0,0 +1,8 @@ +#cmakedefine01 HAVE_STRUCT_UCRED +#cmakedefine01 HAVE_SETPRIORITY +#cmakedefine01 HAVE_GETPEEREID +#cmakedefine01 HAVE_X11 +#cmakedefine01 HAVE_INITGROUPS +#cmakedefine01 HAVE_SYS_SELECT_H +#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" +#define KDE_INSTALL_FULL_LIBEXECDIR_KF "${KDE_INSTALL_FULL_LIBEXECDIR_KF}" diff --git a/src/defaults.h b/src/defaults.h new file mode 100644 index 0000000..d9cef8f --- /dev/null +++ b/src/defaults.h @@ -0,0 +1,19 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + SPDX-License-Identifier: GPL-2.0-only +*/ + +#ifndef KDESUDEFAULTS_H +#define KDESUDEFAULTS_H + +namespace KDESu +{ +const int defTimeout = 120 * 60; +const int defEchoMode = 0; +const bool defKeep = false; + +} + +#endif diff --git a/src/kcookie.cpp b/src/kcookie.cpp new file mode 100644 index 0000000..f4a132a --- /dev/null +++ b/src/kcookie.cpp @@ -0,0 +1,116 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + SPDX-License-Identifier: GPL-2.0-only + + kcookie.cpp: KDE authentication cookies. +*/ + +#include "kcookie_p.h" + +#include + +#include +#include +#include +#include + +extern int kdesuDebugArea(); + +namespace KDESu +{ +namespace KDESuPrivate +{ +class KCookiePrivate +{ +public: + QByteArray display; +#if HAVE_X11 + QByteArray displayAuth; +#endif +}; + +KCookie::KCookie() + : d(new KCookiePrivate) +{ +#if HAVE_X11 + getXCookie(); +#endif +} + +KCookie::~KCookie() = default; + +QByteArray KCookie::display() const +{ + return d->display; +} + +#if HAVE_X11 +QByteArray KCookie::displayAuth() const +{ + return d->displayAuth; +} +#endif + +void KCookie::getXCookie() +{ +#if HAVE_X11 + d->display = qgetenv("DISPLAY"); + if (d->display.isEmpty()) { + // maybe we are on Wayland? + d->display = qgetenv("WAYLAND_DISPLAY"); + if (!d->display.isEmpty()) { + // don't go into the xauth code path + return; + } + } +#else + d->display = qgetenv("QWS_DISPLAY"); +#endif + if (d->display.isEmpty()) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "$DISPLAY is not set."; + return; + } +#if HAVE_X11 // No need to mess with X Auth stuff + QByteArray disp = d->display; + if (disp.startsWith("localhost:")) { // krazy:exclude=strings + disp.remove(0, 9); + } + + const QString xauthExec = QStandardPaths::findExecutable(QStringLiteral("xauth")); + if (xauthExec.isEmpty()) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "Could not run xauth, not found in path"; + return; + } + + QProcess proc; + proc.start(xauthExec, QStringList{QStringLiteral("list"), QString::fromUtf8(disp)}); + if (!proc.waitForStarted()) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "Could not run xauth. Found in path:" << xauthExec; + return; + } + proc.waitForReadyRead(100); + + QByteArray output = proc.readLine().simplified(); + if (output.isEmpty()) { + qCWarning(KSU_LOG) << "No X authentication info set for display" << d->display; + return; + } + + QList lst = output.split(' '); + if (lst.count() != 3) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "parse error."; + return; + } + d->displayAuth = (lst[1] + ' ' + lst[2]); + proc.waitForFinished(100); // give QProcess a chance to clean up gracefully +#endif +} + +} // namespace KDESuPrivate +} // namespace KDESu diff --git a/src/kcookie_p.h b/src/kcookie_p.h new file mode 100644 index 0000000..9140381 --- /dev/null +++ b/src/kcookie_p.h @@ -0,0 +1,58 @@ +/* + This file is part of the KDE project, module kdesu + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + SPDX-License-Identifier: GPL-2.0-only +*/ + +#ifndef KDESUKCOOKIE_H +#define KDESUKCOOKIE_H + +#include + +#include + +#include + +namespace KDESu +{ +namespace KDESuPrivate +{ +/** + * Utility class to access the authentication tokens needed to run a KDE + * program (X11 cookies on X11, for instance). + * @internal + */ + +class KCookie +{ +public: + KCookie(); + ~KCookie(); + + KCookie(const KCookie &) = delete; + KCookie &operator=(const KCookie &) = delete; + + /** + * Returns the X11 display. + */ + QByteArray display() const; + +#if HAVE_X11 + /** + * Returns the X11 magic cookie, if available. + */ + QByteArray displayAuth() const; +#endif + +private: + void getXCookie(); + +private: + std::unique_ptr const d; +}; + +} +} + +#endif // KDESUKCOOKIE_H diff --git a/src/kdesu_stub.c b/src/kdesu_stub.c new file mode 100644 index 0000000..1ace615 --- /dev/null +++ b/src/kdesu_stub.c @@ -0,0 +1,392 @@ +/* + kdesu_stub.c: KDE su executes this stub through su or ssh. This stub in turn + executes the target program. Before that, startup parameters + are sent through stdin. + + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + SPDX-License-Identifier: LGPL-2.0-or-later + + + Available parameters: + + Parameter Description Format (csl = comma separated list) + + - kdesu_stub Header "ok" | "stop" + - display X11 display string + - display_auth X11 authentication "type cookie" pair + - command Command to run string + - path PATH env. var string + - build_sycoca Rebuild sycoca? "yes" | "no" + - user Target user string + - priority Process priority 0 <= int <= 100 + - scheduler Process scheduler "fifo" | "normal" + - app_startup_id DESKTOP_STARTUP_ID string + - environment Additional envvars strings, last one is empty +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_INITGROUPS +#include +#endif + +#include +#include +#include +#include +#include + +#ifdef POSIX1B_SCHEDULING +#include +#endif + +/** + * Params sent by the peer. + */ + +struct param_struct { + const char *name; + char *value; +}; + +struct param_struct params[] = {{"kdesu_stub", 0L}, + {"display", 0L}, + {"display_auth", 0L}, + {"command", 0L}, + {"path", 0L}, + {"xwindows_only", 0L}, + {"user", 0L}, + {"priority", 0L}, + {"scheduler", 0L}, + /* obsoleted by app_startup_id { "app_start_pid", 0L } */ + {"app_startup_id", 0L}}; + +#define P_HEADER 0 +#define P_DISPLAY 1 +#define P_DISPLAY_AUTH 2 +#define P_COMMAND 3 +#define P_PATH 4 +#define P_XWIN_ONLY 5 +#define P_USER 6 +#define P_PRIORITY 7 +#define P_SCHEDULER 8 +#define P_APP_STARTUP_ID 9 +#define P_LAST 10 + +/** + * Safe malloc functions. + */ +char *xmalloc(size_t size) +{ + char *ptr = malloc(size); + if (ptr) { + return ptr; + } + perror("malloc()"); + exit(1); +} + +char **xrealloc(char **ptr, int size) +{ + ptr = realloc(ptr, size); + if (ptr) { + return ptr; + } + perror("realloc()"); + exit(1); +} + +/** + * Solaris does not have a setenv()... + */ +int xsetenv(const char *name, const char *value) +{ + char *s = malloc(strlen(name) + strlen(value) + 2); + if (!s) { + return -1; + } + strcpy(s, name); + strcat(s, "="); + strcat(s, value); + return putenv(s); /* yes: no free()! */ +} + +/** + * Safe strdup and strip newline + */ +char *xstrdup(char *src) +{ + int len = strlen(src); + char *dst = xmalloc(len + 1); + strcpy(dst, src); + if (dst[len - 1] == '\n') { + dst[len - 1] = '\000'; + } + return dst; +} + +/** + * Split comma separated list. + */ +char **xstrsep(char *str) +{ + int i = 0; + int size = 10; + char **list = (char **)xmalloc(size * sizeof(char *)); + char *ptr = str; + char *nptr; + while ((nptr = strchr(ptr, ',')) != 0L) { + if (i > size - 2) { + list = xrealloc(list, (size *= 2) * sizeof(char *)); + } + *nptr = '\000'; + list[i++] = ptr; + ptr = nptr + 1; + } + if (*ptr != '\000') { + list[i++] = ptr; + } + list[i] = 0L; + return list; +} + +#define BUFSIZE 8192 + +static void dequote(char *buf) +{ + char *in; + char *out; + for (in = buf, out = buf; *in; in++, out++) { + char c = *in; + if (c == '\\') { + c = *++in; + if (c == '/') { + *out = '\\'; + } else { + *out = c - '@'; + } + } else { + *out = c; + } + } + *out = 0; +} + +/** + * The main program + */ + +int main() +{ + char buf[BUFSIZE + 1]; + char xauthority[200]; + int i; + int prio; + pid_t pid; + FILE *fout; + struct passwd *pw; + const char *kdesu_lc_all; + + xauthority[0] = '\0'; + + /* Get startup parameters. */ + + for (i = 0; i < P_LAST; i++) { + printf("%s\n", params[i].name); + fflush(stdout); + if (fgets(buf, BUFSIZE, stdin) == 0L) { + printf("end\n"); + fflush(stdout); + perror("kdesu_stub: fgets()"); + exit(1); + } + params[i].value = xstrdup(buf); + /* Installation check? */ + if (i == 0 && !strcmp(params[i].value, "stop")) { + printf("end\n"); + exit(0); + } + } + printf("environment\n"); + fflush(stdout); + for (;;) { + char *tmp; + if (fgets(buf, BUFSIZE, stdin) == 0L) { + printf("end\n"); + fflush(stdout); + perror("kdesu_stub: fgets()"); + exit(1); + } + dequote(buf); + tmp = xstrdup(buf); + if (tmp[0] == '\0') { /* terminator */ + break; + } + putenv(tmp); + } + + printf("end\n"); + fflush(stdout); + + xsetenv("PATH", params[P_PATH].value); + xsetenv("DESKTOP_STARTUP_ID", params[P_APP_STARTUP_ID].value); + + kdesu_lc_all = getenv("KDESU_LC_ALL"); + if (kdesu_lc_all != NULL) { + xsetenv("LC_ALL", kdesu_lc_all); + } else { + unsetenv("LC_ALL"); + } + + unsetenv("XDG_RUNTIME_DIR"); + + /* Do we need to change uid? */ + + pw = getpwnam(params[P_USER].value); + if (pw == 0L) { + printf("kdesu_stub: user %s does not exist!\n", params[P_USER].value); + exit(1); + } + xsetenv("HOME", pw->pw_dir); + + /* New user won't be able to connect it anyway. */ + unsetenv("DBUS_SESSION_BUS_ADDRESS"); + + /* Set scheduling/priority */ + + prio = atoi(params[P_PRIORITY].value); + if (!strcmp(params[P_SCHEDULER].value, "realtime")) { +#ifdef POSIX1B_SCHEDULING + struct sched_param sched; + int min = sched_get_priority_min(SCHED_FIFO); + int max = sched_get_priority_max(SCHED_FIFO); + sched.sched_priority = min + (int)(((double)prio) * (max - min) / 100 + 0.5); + sched_setscheduler(0, SCHED_FIFO, &sched); +#else + printf("kdesu_stub: realtime scheduling not supported\n"); +#endif + } else { +#if HAVE_SETPRIORITY + int val = 20 - (int)(((double)prio) * 40 / 100 + 0.5); + setpriority(PRIO_PROCESS, getpid(), val); +#endif + } + + /* Drop privileges (this is permanent) */ + + if (getuid() != pw->pw_uid) { + if (setgid(pw->pw_gid) == -1) { + perror("kdesu_stub: setgid()"); + exit(1); + } +#if HAVE_INITGROUPS + if (initgroups(pw->pw_name, pw->pw_gid) == -1) { + perror("kdesu_stub: initgroups()"); + exit(1); + } +#endif + if (setuid(pw->pw_uid) == -1) { + perror("kdesu_stub: setuid()"); + exit(1); + } + xsetenv("HOME", pw->pw_dir); + } + + /* Handle display */ + + if (strcmp(params[P_DISPLAY].value, "no")) { + xsetenv("DISPLAY", params[P_DISPLAY].value); + if (params[P_DISPLAY_AUTH].value[0]) { + int fd2; + /* + ** save umask and set to 077, so we create those files only + ** readable for root. (if someone else could read them, we + ** are in deep shit). + */ + int oldumask = umask(077); + const char *disp = params[P_DISPLAY].value; + if (strncmp(disp, "localhost:", 10) == 0) { + disp += 9; + } + + strcpy(xauthority, "/tmp/xauth.XXXXXXXXXX"); + fd2 = mkstemp(xauthority); + umask(oldumask); + + if (fd2 == -1) { + perror("kdesu_stub: mkstemp()"); + exit(1); + } else { + close(fd2); + } + xsetenv("XAUTHORITY", xauthority); + + fout = popen("xauth >/dev/null 2>&1", "w"); + if (fout == NULL) { + perror("kdesu_stub: popen(xauth)"); + exit(1); + } + fprintf(fout, "add %s %s\n", disp, params[P_DISPLAY_AUTH].value); + pclose(fout); + } + } + + /* Rebuild the sycoca and start kdeinit? */ + + if (strcmp(params[P_XWIN_ONLY].value, "no")) { + system("kdeinit5 --suicide"); + } + + /* Execute the command */ + + pid = fork(); + if (pid == -1) { + perror("kdesu_stub: fork()"); + exit(1); + } + if (pid) { + /* Parent: wait for child, delete tempfiles and return. */ + int ret; + int state; + int xit = 1; + while (1) { + ret = waitpid(pid, &state, 0); + if (ret == -1) { + if (errno == EINTR) { + continue; + } + if (errno != ECHILD) { + perror("kdesu_stub: waitpid()"); + } + break; + } + if (WIFEXITED(state)) { + xit = WEXITSTATUS(state); + } + } + + if (*xauthority) { + unlink(xauthority); + } + exit(xit); + } else { + setsid(); + /* Child: exec command. */ + sprintf(buf, "%s", params[P_COMMAND].value); + dequote(buf); + execl("/bin/sh", "sh", "-c", buf, (void *)0); + perror("kdesu_stub: exec()"); + _exit(1); + } +} diff --git a/src/kdesud/CMakeLists.txt b/src/kdesud/CMakeLists.txt new file mode 100644 index 0000000..9eaed46 --- /dev/null +++ b/src/kdesud/CMakeLists.txt @@ -0,0 +1,49 @@ +include(CheckFunctionExists) +check_function_exists(getpeereid HAVE_GETPEEREID) # openbsd style +check_function_exists(getpeereucred HAVE_GETPEERUCRED) # solaris style + +check_symbol_exists(close_range "unistd.h" HAVE_CLOSE_RANGE) + +configure_file (config-kdesud.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kdesud.h ) + +add_executable(kdesud) +ecm_mark_nongui_executable(kdesud) + +target_sources(kdesud PRIVATE + kdesud.cpp + repo.cpp + lexer.cpp + handler.cpp + secure.cpp +) + +ecm_qt_declare_logging_category(kdesud + HEADER ksud_debug.h + IDENTIFIER KSUD_LOG + CATEGORY_NAME kf.su.kdesud + DESCRIPTION "kdesud (KDESu)" + EXPORT KSU +) + +target_link_libraries(kdesud KF5::Su KF5::I18n ${X11_LIBRARIES}) +if(HAVE_X11) + target_include_directories(kdesud PRIVATE ${X11_X11_INCLUDE_PATH}) +endif() + +if(KDE4_ENABLE_FPIE) + macro_add_compile_flags(kdesud ${KDE4_CXX_FPIE_FLAGS}) + macro_add_link_flags(kdesud ${KDE4_PIE_LDFLAGS}) +endif() + +if(BUILD_TESTING) + add_subdirectory(autotests) +endif() + +########### install files ############### + +install(TARGETS kdesud DESTINATION ${KDE_INSTALL_LIBEXECDIR_KF}) +install(CODE " + set(KDESUD_PATH \"\$ENV{DESTDIR}${KDE_INSTALL_FULL_LIBEXECDIR_KF}/kdesud\") + execute_process(COMMAND sh -c \"chgrp nogroup '\${KDESUD_PATH}' && chmod g+s '\${KDESUD_PATH}'\") +") + diff --git a/src/kdesud/Messages.sh b/src/kdesud/Messages.sh new file mode 100644 index 0000000..e7a3a20 --- /dev/null +++ b/src/kdesud/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/kdesud5.pot diff --git a/src/kdesud/autotests/CMakeLists.txt b/src/kdesud/autotests/CMakeLists.txt new file mode 100644 index 0000000..6fcdd2e --- /dev/null +++ b/src/kdesud/autotests/CMakeLists.txt @@ -0,0 +1,4 @@ +include(ECMAddTests) +find_package(Qt${QT_MAJOR_VERSION}Test REQUIRED) +configure_file(config-kdesudtest.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kdesudtest.h) +ecm_add_test(kdesudtest.cpp ../lexer.cpp TEST_NAME kdesudtest LINK_LIBRARIES Qt${QT_MAJOR_VERSION}::Test KF5::CoreAddons KF5::ConfigCore) diff --git a/src/kdesud/autotests/config-kdesudtest.h.cmake b/src/kdesud/autotests/config-kdesudtest.h.cmake new file mode 100644 index 0000000..5f320cc --- /dev/null +++ b/src/kdesud/autotests/config-kdesudtest.h.cmake @@ -0,0 +1,2 @@ +#define CMAKE_HOME_DIRECTORY "${CMAKE_HOME_DIRECTORY}" +#define CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" diff --git a/src/kdesud/autotests/kdesudtest.cpp b/src/kdesud/autotests/kdesudtest.cpp new file mode 100644 index 0000000..a75f721 --- /dev/null +++ b/src/kdesud/autotests/kdesudtest.cpp @@ -0,0 +1,72 @@ +/* + SPDX-FileCopyrightText: 2020 Aleksei Nikiforov + + SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +*/ + +#include "config-kdesudtest.h" + +#include +#include + +#include "../lexer.h" + +namespace KDESu +{ +class KdeSudTest : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void initTestCase() + { + } + + // copy of KDEsuClient::escape + QByteArray escape(const QByteArray &str) + { + QByteArray copy; + copy.reserve(str.size() + 4); + copy.append('"'); + for (const uchar c : str) { + if (c < 32) { + copy.append('\\'); + copy.append('^'); + copy.append(c + '@'); + } else { + if (c == '\\' || c == '"') { + copy.append('\\'); + } + copy.append(c); + } + } + copy.append('"'); + return copy; + } + + void commandWithDoubleQuotes() + { + // Process command like in KDEsuClient::exec + QByteArray cmd; + cmd = "EXEC "; + cmd += escape("bash -c \"ls -la\""); + cmd += ' '; + cmd += escape("testuser"); + cmd += '\n'; + + // Now handle command like in ConnectionHandler::doCommand + Lexer l(cmd); + QVERIFY(l.lex() == Lexer::Tok_exec); + + QVERIFY(l.lex() == Lexer::Tok_str); + QVERIFY(l.lval() == "bash -c \"ls -la\""); + + QVERIFY(l.lex() == Lexer::Tok_str); + QVERIFY(l.lval() == "testuser"); + + QVERIFY(l.lex() == '\n'); + } +}; +} + +#include +QTEST_MAIN(KDESu::KdeSudTest) diff --git a/src/kdesud/config-kdesud.h.cmake b/src/kdesud/config-kdesud.h.cmake new file mode 100644 index 0000000..4d420b4 --- /dev/null +++ b/src/kdesud/config-kdesud.h.cmake @@ -0,0 +1,9 @@ +/* config-kdesud.h. Generated by cmake from config-kdesud.h.cmake */ + +/* Define to 1 if you have the `getpeereid' function. */ +#cmakedefine01 HAVE_GETPEEREID + +/* Define to 1 if you have the `getpeerucred' function. */ +#cmakedefine01 HAVE_GETPEERUCRED + +#cmakedefine01 HAVE_CLOSE_RANGE diff --git a/src/kdesud/handler.cpp b/src/kdesud/handler.cpp new file mode 100644 index 0000000..09ffd9b --- /dev/null +++ b/src/kdesud/handler.cpp @@ -0,0 +1,539 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + handler.cpp: A connection handler for kdesud. +*/ + +#include "handler.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "lexer.h" +#include "repo.h" + +using namespace KDESu; + +#define BUF_SIZE 1024 + +// Global repository +extern Repository *repo; +void kdesud_cleanup(); + +ConnectionHandler::ConnectionHandler(int fd) + : SocketSecurity(fd) + , m_exitCode(0) + , m_hasExitCode(false) + , m_needExitCode(false) + , m_pid(0) +{ + m_Fd = fd; + m_Priority = 50; + m_Scheduler = SuProcess::SchedNormal; +} + +ConnectionHandler::~ConnectionHandler() +{ + m_Buf.fill('x'); + m_Pass.fill('x'); + close(m_Fd); +} + +/* + * Handle a connection: make sure we don't block + */ + +int ConnectionHandler::handle() +{ + int ret; + int nbytes; + + m_Buf.reserve(BUF_SIZE); + nbytes = recv(m_Fd, m_Buf.data() + m_Buf.size(), BUF_SIZE - 1 - m_Buf.size(), 0); + + if (nbytes < 0) { + if (errno == EINTR) { + return 0; + } + // read error + return -1; + } else if (nbytes == 0) { + // eof + return -1; + } + + m_Buf.resize(m_Buf.size() + nbytes); + if (m_Buf.size() == BUF_SIZE - 1) { + qCWarning(KSUD_LOG) << "line too long"; + return -1; + } + + // Do we have a complete command yet? + int n; + while ((n = m_Buf.indexOf('\n')) != -1) { + n++; + QByteArray newbuf = QByteArray(m_Buf.data(), n); // ensure new detached buffer for simplicity + int nsize = m_Buf.size() - n; + ::memmove(m_Buf.data(), m_Buf.data() + n, nsize); + ::memset(m_Buf.data() + nsize, 'x', n); + m_Buf.resize(nsize); + ret = doCommand(newbuf); + if (newbuf.isDetached()) { // otherwise somebody else will clear it + newbuf.fill('x'); + } + if (ret < 0) { + return ret; + } + } + + return 0; +} + +QByteArray ConnectionHandler::makeKey(int _namespace, const QByteArray &s1, const QByteArray &s2, const QByteArray &s3) const +{ + QByteArray res; + res.setNum(_namespace); + res += '*'; + res += s1 + '*' + s2 + '*' + s3; + return res; +} + +void ConnectionHandler::sendExitCode() +{ + if (!m_needExitCode) { + return; + } + QByteArray buf; + buf.setNum(m_exitCode); + buf.prepend("OK "); + buf.append("\n"); + + send(m_Fd, buf.data(), buf.length(), 0); +} + +void ConnectionHandler::respond(int ok, const QByteArray &s) +{ + QByteArray buf; + + switch (ok) { + case Res_OK: + buf = "OK"; + break; + case Res_NO: + default: + buf = "NO"; + break; + } + + if (!s.isEmpty()) { + buf += ' '; + buf += s; + } + + buf += '\n'; + + send(m_Fd, buf.data(), buf.length(), 0); +} + +/* + * Parse and do one command. On a parse error, return -1. This will + * close the socket in the main accept loop. + */ + +int ConnectionHandler::doCommand(QByteArray buf) +{ + if ((uid_t)peerUid() != getuid()) { + qCWarning(KSUD_LOG) << "Peer uid not equal to me\n"; + qCWarning(KSUD_LOG) << "Peer: " << peerUid() << " Me: " << getuid(); + return -1; + } + + QByteArray key; + QByteArray command; + QByteArray pass; + QByteArray name; + QByteArray user; + QByteArray value; + QByteArray env_check; + Data_entry data; + + Lexer *l = new Lexer(buf); + int tok = l->lex(); + switch (tok) { + case Lexer::Tok_pass: // "PASS password:string timeout:int\n" + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + m_Pass.fill('x'); + m_Pass = l->lval(); + tok = l->lex(); + if (tok != Lexer::Tok_num) { + goto parse_error; + } + m_Timeout = l->lval().toInt(); + if (l->lex() != '\n') { + goto parse_error; + } + if (m_Pass.isNull()) { + m_Pass = ""; + } + qCDebug(KSUD_LOG) << "Password set!\n"; + respond(Res_OK); + break; + + case Lexer::Tok_host: // "HOST host:string\n" + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + m_Host = l->lval(); + if (l->lex() != '\n') { + goto parse_error; + } + qCDebug(KSUD_LOG) << "Host set to " << m_Host; + respond(Res_OK); + break; + + case Lexer::Tok_prio: // "PRIO priority:int\n" + tok = l->lex(); + if (tok != Lexer::Tok_num) { + goto parse_error; + } + m_Priority = l->lval().toInt(); + if (l->lex() != '\n') { + goto parse_error; + } + qCDebug(KSUD_LOG) << "priority set to " << m_Priority; + respond(Res_OK); + break; + + case Lexer::Tok_sched: // "SCHD scheduler:int\n" + tok = l->lex(); + if (tok != Lexer::Tok_num) { + goto parse_error; + } + m_Scheduler = l->lval().toInt(); + if (l->lex() != '\n') { + goto parse_error; + } + qCDebug(KSUD_LOG) << "Scheduler set to " << m_Scheduler; + respond(Res_OK); + break; + + case Lexer::Tok_exec: // "EXEC command:string user:string [options:string (env:string)*]\n" + { + QByteArray options; + QList env; + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + command = l->lval(); + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + user = l->lval(); + tok = l->lex(); + if (tok != '\n') { + if (tok != Lexer::Tok_str) { + goto parse_error; + } + options = l->lval(); + tok = l->lex(); + while (tok != '\n') { + if (tok != Lexer::Tok_str) { + goto parse_error; + } + QByteArray env_str = l->lval(); + env.append(env_str); + if (strncmp(env_str.constData(), "DESKTOP_STARTUP_ID=", strlen("DESKTOP_STARTUP_ID=")) != 0) { + env_check += '*' + env_str; + } + tok = l->lex(); + } + } + + QByteArray auth_user; + if ((m_Scheduler != SuProcess::SchedNormal) || (m_Priority > 50)) { + auth_user = "root"; + } else { + auth_user = user; + } + key = makeKey(2, m_Host, auth_user, command); + // We only use the command if the environment is the same. + if (repo->find(key) == env_check) { + key = makeKey(0, m_Host, auth_user, command); + pass = repo->find(key); + } + if (pass.isNull()) // isNull() means no password, isEmpty() can mean empty password + { + if (m_Pass.isNull()) { + respond(Res_NO); + break; + } + data.value = env_check; + data.timeout = m_Timeout; + key = makeKey(2, m_Host, auth_user, command); + repo->add(key, data); + data.value = m_Pass; + data.timeout = m_Timeout; + key = makeKey(0, m_Host, auth_user, command); + repo->add(key, data); + pass = m_Pass; + } + + // Execute the command asynchronously + qCDebug(KSUD_LOG) << "Executing command: " << command; + pid_t pid = fork(); + if (pid < 0) { + qCDebug(KSUD_LOG) << "fork(): " << strerror(errno); + respond(Res_NO); + break; + } else if (pid > 0) { + m_pid = pid; + respond(Res_OK); + break; + } + + // Ignore SIGCHLD because "class SuProcess" needs waitpid() + signal(SIGCHLD, SIG_DFL); + + int ret; + if (m_Host.isEmpty()) { + SuProcess proc; + proc.setCommand(command); + proc.setUser(user); + if (options.contains('x')) { + proc.setXOnly(true); + } + proc.setPriority(m_Priority); + proc.setScheduler(m_Scheduler); + proc.setEnvironment(env); + ret = proc.exec(pass.data()); + } else { + SshProcess proc; + proc.setCommand(command); + proc.setUser(user); + proc.setHost(m_Host); + ret = proc.exec(pass.data()); + } + + qCDebug(KSUD_LOG) << "Command completed: " << command; + _exit(ret); + } + + case Lexer::Tok_delCmd: // "DEL command:string user:string\n" + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + command = l->lval(); + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + user = l->lval(); + if (l->lex() != '\n') { + goto parse_error; + } + key = makeKey(0, m_Host, user, command); + if (repo->remove(key) < 0) { + qCDebug(KSUD_LOG) << "Unknown command: " << command; + respond(Res_NO); + } else { + qCDebug(KSUD_LOG) << "Deleted command: " << command << ", user = " << user; + respond(Res_OK); + } + break; + + case Lexer::Tok_delVar: // "DELV name:string \n" + { + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + name = l->lval(); + tok = l->lex(); + if (tok != '\n') { + goto parse_error; + } + key = makeKey(1, name); + if (repo->remove(key) < 0) { + qCDebug(KSUD_LOG) << "Unknown name: " << name; + respond(Res_NO); + } else { + qCDebug(KSUD_LOG) << "Deleted name: " << name; + respond(Res_OK); + } + break; + } + + case Lexer::Tok_delGroup: // "DELG group:string\n" + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + name = l->lval(); + if (repo->removeGroup(name) < 0) { + qCDebug(KSUD_LOG) << "No keys found under group: " << name; + respond(Res_NO); + } else { + qCDebug(KSUD_LOG) << "Removed all keys under group: " << name; + respond(Res_OK); + } + break; + + case Lexer::Tok_delSpecialKey: // "DELS special_key:string\n" + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + name = l->lval(); + if (repo->removeSpecialKey(name) < 0) { + respond(Res_NO); + } else { + respond(Res_OK); + } + break; + + case Lexer::Tok_set: // "SET name:string value:string group:string timeout:int\n" + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + name = l->lval(); + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + data.value = l->lval(); + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + data.group = l->lval(); + tok = l->lex(); + if (tok != Lexer::Tok_num) { + goto parse_error; + } + data.timeout = l->lval().toInt(); + if (l->lex() != '\n') { + goto parse_error; + } + key = makeKey(1, name); + repo->add(key, data); + qCDebug(KSUD_LOG) << "Stored key: " << key; + respond(Res_OK); + break; + + case Lexer::Tok_get: // "GET name:string\n" + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + name = l->lval(); + if (l->lex() != '\n') { + goto parse_error; + } + key = makeKey(1, name); + qCDebug(KSUD_LOG) << "Request for key: " << key; + value = repo->find(key); + if (!value.isEmpty()) { + respond(Res_OK, value); + } else { + respond(Res_NO); + } + break; + + case Lexer::Tok_getKeys: // "GETK groupname:string\n" + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + name = l->lval(); + if (l->lex() != '\n') { + goto parse_error; + } + qCDebug(KSUD_LOG) << "Request for group key: " << name; + value = repo->findKeys(name); + if (!value.isEmpty()) { + respond(Res_OK, value); + } else { + respond(Res_NO); + } + break; + + case Lexer::Tok_chkGroup: // "CHKG groupname:string\n" + tok = l->lex(); + if (tok != Lexer::Tok_str) { + goto parse_error; + } + name = l->lval(); + if (l->lex() != '\n') { + goto parse_error; + } + qCDebug(KSUD_LOG) << "Checking for group key: " << name; + if (repo->hasGroup(name) < 0) { + respond(Res_NO); + } else { + respond(Res_OK); + } + break; + + case Lexer::Tok_ping: // "PING\n" + tok = l->lex(); + if (tok != '\n') { + goto parse_error; + } + respond(Res_OK); + break; + + case Lexer::Tok_exit: // "EXIT\n" + tok = l->lex(); + if (tok != '\n') { + goto parse_error; + } + m_needExitCode = true; + if (m_hasExitCode) { + sendExitCode(); + } + break; + + case Lexer::Tok_stop: // "STOP\n" + tok = l->lex(); + if (tok != '\n') { + goto parse_error; + } + qCDebug(KSUD_LOG) << "Stopping by command"; + respond(Res_OK); + kdesud_cleanup(); + exit(0); + + default: + qCWarning(KSUD_LOG) << "Unknown command: " << l->lval(); + respond(Res_NO); + goto parse_error; + } + + delete l; + return 0; + +parse_error: + qCWarning(KSUD_LOG) << "Parse error"; + delete l; + return -1; +} diff --git a/src/kdesud/handler.h b/src/kdesud/handler.h new file mode 100644 index 0000000..6b190bb --- /dev/null +++ b/src/kdesud/handler.h @@ -0,0 +1,58 @@ +/* vi: ts=8 sts=4 sw=4 + + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen +*/ + +#ifndef __Handler_h_included__ +#define __Handler_h_included__ + +#include + +#include "secure.h" +#include + +/** + * A ConnectionHandler handles a client. It is called from the main program + * loop whenever there is data to read from a corresponding socket. + * It keeps reading data until a newline is read. Then, a command is parsed + * and executed. + */ + +class ConnectionHandler : public SocketSecurity +{ +public: + ConnectionHandler(int fd); + ~ConnectionHandler(); + + ConnectionHandler(const ConnectionHandler &) = delete; + ConnectionHandler &operator=(const ConnectionHandler &) = delete; + + /** Handle incoming data. */ + int handle(); + + /* Send back exit code. */ + void sendExitCode(); + +private: + enum Results { + Res_OK, + Res_NO, + }; + + int doCommand(QByteArray buf); + void respond(int ok, const QByteArray &s = QByteArray()); + QByteArray makeKey(int namspace, const QByteArray &s1, const QByteArray &s2 = QByteArray(), const QByteArray &s3 = QByteArray()) const; + + int m_Fd, m_Timeout; + int m_Priority, m_Scheduler; + QByteArray m_Buf, m_Pass, m_Host; + +public: + int m_exitCode; + bool m_hasExitCode; + bool m_needExitCode; + pid_t m_pid; +}; + +#endif diff --git a/src/kdesud/kdesud.cpp b/src/kdesud/kdesud.cpp new file mode 100644 index 0000000..d79d9d0 --- /dev/null +++ b/src/kdesud/kdesud.cpp @@ -0,0 +1,510 @@ +/* vi: ts=8 sts=4 sw=4 + + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + + kdesud.cpp: KDE su daemon. Offers "keep password" functionality to kde su. + + The socket $KDEHOME/socket-$(HOSTNAME)/kdesud_$(display) is used for communication with + client programs. + + The protocol: Client initiates the connection. All commands and responses + are terminated by a newline. + + Client Server Description + ------ ------ ----------- + + PASS OK Set password for commands in + this session. Password is + valid for seconds. + + USER OK Set the target user [required] + + EXEC OK Execute command . If + NO has been executed + before (< timeout) no PASS + command is needed. + + DEL OK Delete password for command + NO . + + PING OK Ping the server (diagnostics). +*/ + +#include "config-kdesud.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include // Needed on some systems. +#endif + +#include + +#if !HAVE_CLOSE_RANGE +#include // close_range syscall +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "handler.h" +#include "repo.h" + +#if HAVE_X11 +#include +#include +#endif + +#ifndef SUN_LEN +#define SUN_LEN(ptr) ((socklen_t)(offsetof(struct sockaddr_un, sun_path) + strlen((ptr)->sun_path))) +#endif + +#define ERR strerror(errno) + +using namespace KDESu; + +static int closeExtraFds() +{ +#if HAVE_CLOSE_RANGE + const int res = close_range(4, ~0U, 0); + if (res == 0) { + return 0; + } + // If ENOSYS, fallback to opendir/readdir/closedir below + if (errno != ENOSYS) { + return -1; + } +#elif defined(SYS_close_range) + const int res = syscall(SYS_close_range, 4, ~0U, 0); + if (res == 0) { + return 0; + } + // If ENOSYS, fallback to opendir/readdir/closedir below + if (errno != ENOSYS) { + return -1; + } +#endif + +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) // /proc, /dev are Linux only + // close_range isn't available, fallback to iterarting over "/dev/fd/" + // and close the fd's manually + qCDebug(KSUD_LOG) << "close_range function/syscall isn't available, falling back to iterarting " + "over '/dev/fd' and closing the file descriptors manually.\n"; + + std::unique_ptr dirPtr(opendir("/dev/fd"), closedir); + if (!dirPtr) { + return -1; + } + + int closeRes = 0; + const int dirFd = dirfd(dirPtr.get()); + while (struct dirent *dirEnt = readdir(dirPtr.get())) { + const int currFd = std::atoi(dirEnt->d_name); + if (currFd > 3 && currFd != dirFd) { + closeRes = close(currFd); + if (closeRes == -1) { + break; + } + } + } + return closeRes; +#else + return -1; +#endif +} + +// Globals + +Repository *repo; +QString Version(QStringLiteral("1.01")); +QByteArray sock; +#if HAVE_X11 +Display *x11Display; +#endif +int pipeOfDeath[2]; + +void kdesud_cleanup() +{ + unlink(sock.constData()); +} + +// Borrowed from kdebase/kaudio/kaudioserver.cpp + +#if HAVE_X11 +extern "C" int xio_errhandler(Display *); + +int xio_errhandler(Display *) +{ + qCCritical(KSUD_LOG) << "Fatal IO error, exiting...\n"; + kdesud_cleanup(); + exit(1); + return 1; // silence compilers +} + +int initXconnection() +{ + x11Display = XOpenDisplay(nullptr); + if (x11Display != nullptr) { + XSetIOErrorHandler(xio_errhandler); + /* clang-format off */ + XCreateSimpleWindow(x11Display, + DefaultRootWindow(x11Display), + 0, 0, 1, 1, 0, + BlackPixelOfScreen(DefaultScreenOfDisplay(x11Display)), + BlackPixelOfScreen(DefaultScreenOfDisplay(x11Display))); + /* clang-format on*/ + return XConnectionNumber(x11Display); + } else { + qCWarning(KSUD_LOG) << "Can't connect to the X Server.\n"; + qCWarning(KSUD_LOG) << "Might not terminate at end of session.\n"; + return -1; + } +} +#endif + +extern "C" { +void signal_exit(int); +void sigchld_handler(int); +} + +void signal_exit(int sig) +{ + qCDebug(KSUD_LOG) << "Exiting on signal " << sig << "\n"; + kdesud_cleanup(); + exit(1); +} + +void sigchld_handler(int) +{ + char c = ' '; + write(pipeOfDeath[1], &c, 1); +} + +/** + * Creates an AF_UNIX socket in socket resource, mode 0600. + */ + +int create_socket() +{ + int sockfd; + socklen_t addrlen; + struct stat s; + + QString display = QString::fromLocal8Bit(qgetenv("DISPLAY")); + if (display.isEmpty()) { + qCWarning(KSUD_LOG) << "$DISPLAY is not set\n"; + return -1; + } + + // strip the screen number from the display + display.remove(QRegularExpression(QStringLiteral("\\.[0-9]+$"))); + + sock = QFile::encodeName(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) + QStringLiteral("/kdesud_%1").arg(display)); + int stat_err = lstat(sock.constData(), &s); + if (!stat_err && S_ISLNK(s.st_mode)) { + qCWarning(KSUD_LOG) << "Someone is running a symlink attack on you\n"; + if (unlink(sock.constData())) { + qCWarning(KSUD_LOG) << "Could not delete symlink\n"; + return -1; + } + } + + if (!access(sock.constData(), R_OK | W_OK)) { + KDEsuClient client; + if (client.ping() == -1) { + qCWarning(KSUD_LOG) << "stale socket exists\n"; + if (unlink(sock.constData())) { + qCWarning(KSUD_LOG) << "Could not delete stale socket\n"; + return -1; + } + } else { + qCWarning(KSUD_LOG) << "kdesud is already running\n"; + return -1; + } + } + + sockfd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (sockfd < 0) { + qCCritical(KSUD_LOG) << "socket(): " << ERR << "\n"; + return -1; + } + + // Ensure socket closed on error + struct fd_ScopeGuard { + fd_ScopeGuard(int fd) + : _fd(fd) + { + } + ~fd_ScopeGuard() + { + if (_fd >= 0) { + close(_fd); + } + } + fd_ScopeGuard(const fd_ScopeGuard &) = delete; + fd_ScopeGuard &operator=(const fd_ScopeGuard &) = delete; + void reset() + { + _fd = -1; + } + int _fd; + } guard(sockfd); + + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, sock.constData(), sizeof(addr.sun_path) - 1); + addr.sun_path[sizeof(addr.sun_path) - 1] = '\000'; + addrlen = SUN_LEN(&addr); + if (bind(sockfd, (struct sockaddr *)&addr, addrlen) < 0) { + qCCritical(KSUD_LOG) << "bind(): " << ERR << "\n"; + return -1; + } + + struct linger lin; + lin.l_onoff = lin.l_linger = 0; + if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (char *)&lin, sizeof(linger)) < 0) { + qCCritical(KSUD_LOG) << "setsockopt(SO_LINGER): " << ERR << "\n"; + return -1; + } + + int opt = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) { + qCCritical(KSUD_LOG) << "setsockopt(SO_REUSEADDR): " << ERR << "\n"; + return -1; + } + opt = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt, sizeof(opt)) < 0) { + qCCritical(KSUD_LOG) << "setsockopt(SO_KEEPALIVE): " << ERR << "\n"; + return -1; + } + chmod(sock.constData(), 0600); + guard.reset(); + return sockfd; +} + +/** + * Main program + */ + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + KAboutData aboutData(QStringLiteral("kdesud") /* componentName */, + i18n("KDE su daemon"), + Version, + i18n("Daemon used by kdesu"), + KAboutLicense::Artistic, + i18n("Copyright (c) 1999,2000 Geert Jansen")); + aboutData.addAuthor(i18n("Geert Jansen"), i18n("Author"), QStringLiteral("jansen@kde.org"), QStringLiteral("http://www.stack.nl/~geertj/")); + + KAboutData::setApplicationData(aboutData); + QCommandLineParser parser; + aboutData.setupCommandLine(&parser); + parser.process(app); + aboutData.processCommandLine(&parser); + + // Set core dump size to 0 + struct rlimit rlim; + rlim.rlim_cur = rlim.rlim_max = 0; + if (setrlimit(RLIMIT_CORE, &rlim) < 0) { + qCCritical(KSUD_LOG) << "setrlimit(): " << ERR << "\n"; + exit(1); + } + + // Create the Unix socket. + int sockfd = create_socket(); + if (sockfd < 0) { + exit(1); + } + if (listen(sockfd, 10) < 0) { + qCCritical(KSUD_LOG) << "listen(): " << ERR << "\n"; + kdesud_cleanup(); + exit(1); + } + + if (sockfd != 3) { + sockfd = dup3(sockfd, 3, O_CLOEXEC); + } + if (sockfd < 0) { + qCCritical(KSUD_LOG) << "Failed to set sockfd to fd 3" << ERR << "\n"; + kdesud_cleanup(); + exit(1); + } + + int maxfd = sockfd; + + if (closeExtraFds() < 0) { + qCCritical(KSUD_LOG) << "Failed to close file descriptors higher than 3, with error:" << ERR << "\n"; + kdesud_cleanup(); + exit(1); + } + + // Ok, we're accepting connections. Fork to the background. + pid_t pid = fork(); + if (pid == -1) { + qCCritical(KSUD_LOG) << "fork():" << ERR << "\n"; + kdesud_cleanup(); + exit(1); + } + if (pid) { + _exit(0); + } + +#if HAVE_X11 + // Make sure we exit when the display gets closed. + int x11Fd = initXconnection(); + maxfd = qMax(maxfd, x11Fd); +#endif + + repo = new Repository; + QVector handler; + + pipe2(pipeOfDeath, O_CLOEXEC); + maxfd = qMax(maxfd, pipeOfDeath[0]); + + // Signal handlers + struct sigaction sa; + sa.sa_handler = signal_exit; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGHUP, &sa, nullptr); + sigaction(SIGINT, &sa, nullptr); + sigaction(SIGTERM, &sa, nullptr); + sigaction(SIGQUIT, &sa, nullptr); + + sa.sa_handler = sigchld_handler; + sa.sa_flags = SA_NOCLDSTOP; + sigaction(SIGCHLD, &sa, nullptr); + sa.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &sa, nullptr); + + // Main execution loop + + socklen_t addrlen; + struct sockaddr_un clientname; + + fd_set tmp_fds; + fd_set active_fds; + FD_ZERO(&active_fds); + FD_SET(sockfd, &active_fds); + FD_SET(pipeOfDeath[0], &active_fds); +#if HAVE_X11 + if (x11Fd != -1) { + FD_SET(x11Fd, &active_fds); + } +#endif + + while (1) { + tmp_fds = active_fds; +#if HAVE_X11 + if (x11Display) { + XFlush(x11Display); + } +#endif + if (select(maxfd + 1, &tmp_fds, nullptr, nullptr, nullptr) < 0) { + if (errno == EINTR) { + continue; + } + + qCCritical(KSUD_LOG) << "select(): " << ERR << "\n"; + exit(1); + } + repo->expire(); + for (int i = 0; i <= maxfd; i++) { + if (!FD_ISSET(i, &tmp_fds)) { + continue; + } + + if (i == pipeOfDeath[0]) { + char buf[101]; + read(pipeOfDeath[0], buf, 100); + pid_t result; + do { + int status; + result = waitpid((pid_t)-1, &status, WNOHANG); + if (result > 0) { + for (int j = handler.size(); j--;) { + if (handler[j] && (handler[j]->m_pid == result)) { + handler[j]->m_exitCode = WEXITSTATUS(status); + handler[j]->m_hasExitCode = true; + handler[j]->sendExitCode(); + handler[j]->m_pid = 0; + break; + } + } + } + } while (result > 0); + } + +#if HAVE_X11 + if (i == x11Fd) { + // Discard X events + XEvent event_return; + if (x11Display) { + while (XPending(x11Display)) { + XNextEvent(x11Display, &event_return); + } + } + continue; + } +#endif + + if (i == sockfd) { + // Accept new connection + int fd; + addrlen = 64; + fd = accept(sockfd, (struct sockaddr *)&clientname, &addrlen); + if (fd < 0) { + qCCritical(KSUD_LOG) << "accept():" << ERR << "\n"; + continue; + } + while (fd + 1 > (int)handler.size()) { + handler.append(nullptr); + } + delete handler[fd]; + handler[fd] = new ConnectionHandler(fd); + maxfd = qMax(maxfd, fd); + FD_SET(fd, &active_fds); + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + continue; + } + + // handle already established connection + if (handler[i] && handler[i]->handle() < 0) { + delete handler[i]; + handler[i] = nullptr; + FD_CLR(i, &active_fds); + } + } + } + qCWarning(KSUD_LOG) << "???\n"; +} diff --git a/src/kdesud/lexer.cpp b/src/kdesud/lexer.cpp new file mode 100644 index 0000000..b168071 --- /dev/null +++ b/src/kdesud/lexer.cpp @@ -0,0 +1,163 @@ +/* vi: ts=8 sts=4 sw=4 + + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + lexer.cpp: A lexer for the kdesud protocol. See kdesud.cpp for a + description of the protocol. +*/ + +#include "lexer.h" + +#include + +Lexer::Lexer(const QByteArray &input) +{ + m_Input = input; + in = 0; +} + +Lexer::~Lexer() +{ + // Erase buffers + m_Input.fill('x'); + m_Output.fill('x'); +} + +QByteArray &Lexer::lval() +{ + return m_Output; +} + +/* + * lex() is the lexer. There is no end-of-input check here so that has to be + * done by the caller. + */ + +int Lexer::lex() +{ + char c; + + c = m_Input[in++]; + m_Output.fill('x'); + m_Output.resize(0); + + while (1) { + // newline? + if (c == '\n') { + return '\n'; + } + + // No control characters + if (iscntrl(c)) { + return Tok_none; + } + + if (isspace(c)) { + while (isspace(c = m_Input[in++])) { + ; + } + } + + // number? + if (isdigit(c)) { + m_Output += c; + while (isdigit(c = m_Input[in++])) { + m_Output += c; + } + in--; + return Tok_num; + } + + // quoted string? + if (c == '"') { + c = m_Input[in++]; + while ((c != '"') && !iscntrl(c)) { + // handle escaped characters + if (c == '\\') { + c = m_Input[in++]; + if (iscntrl(c)) { + return Tok_none; + } + if (c == '^') { + c = m_Input[in++]; + if ((c == '"') || iscntrl(c)) { + return Tok_none; + } + m_Output += c - '@'; + } else { + m_Output += c; + } + } else { + m_Output += c; + } + c = m_Input[in++]; + } + if (c == '"') { + return Tok_str; + } + return Tok_none; + } + + // normal string + while (!isspace(c) && !iscntrl(c)) { + m_Output += c; + c = m_Input[in++]; + } + in--; + + // command? + if (m_Output.length() <= 4) { + if (m_Output == "EXEC") { + return Tok_exec; + } + if (m_Output == "PASS") { + return Tok_pass; + } + if (m_Output == "DEL") { + return Tok_delCmd; + } + if (m_Output == "PING") { + return Tok_ping; + } + if (m_Output == "EXIT") { + return Tok_exit; + } + if (m_Output == "STOP") { + return Tok_stop; + } + if (m_Output == "SET") { + return Tok_set; + } + if (m_Output == "GET") { + return Tok_get; + } + if (m_Output == "HOST") { + return Tok_host; + } + if (m_Output == "SCHD") { + return Tok_sched; + } + if (m_Output == "PRIO") { + return Tok_prio; + } + if (m_Output == "DELV") { + return Tok_delVar; + } + if (m_Output == "DELG") { + return Tok_delGroup; + } + if (m_Output == "DELS") { + return Tok_delSpecialKey; + } + if (m_Output == "GETK") { + return Tok_getKeys; + } + if (m_Output == "CHKG") { + return Tok_chkGroup; + } + } + + return Tok_str; + } +} diff --git a/src/kdesud/lexer.h b/src/kdesud/lexer.h new file mode 100644 index 0000000..c03482a --- /dev/null +++ b/src/kdesud/lexer.h @@ -0,0 +1,60 @@ +/* vi: ts=8 sts=4 sw=4 + + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen +*/ + +#ifndef __Lexer_h_included__ +#define __Lexer_h_included__ + +#include + +/** + * This is a lexer for the kdesud protocol. + */ + +class Lexer +{ +public: + Lexer(const QByteArray &input); + ~Lexer(); + + Lexer(const Lexer &) = delete; + Lexer &operator=(const Lexer &) = delete; + + /** Read next token. */ + int lex(); + + /** Return the token's value. */ + QByteArray &lval(); + + enum Tokens { + Tok_none, + Tok_exec = 256, + Tok_pass, + Tok_delCmd, + Tok_ping, + Tok_str, + Tok_num, + Tok_stop, + Tok_set, + Tok_get, + Tok_delVar, + Tok_delGroup, + Tok_host, + Tok_prio, + Tok_sched, + Tok_getKeys, + Tok_chkGroup, + Tok_delSpecialKey, + Tok_exit, + }; + +private: + QByteArray m_Input; + QByteArray m_Output; + + int in; +}; + +#endif diff --git a/src/kdesud/repo.cpp b/src/kdesud/repo.cpp new file mode 100644 index 0000000..b7676c4 --- /dev/null +++ b/src/kdesud/repo.cpp @@ -0,0 +1,176 @@ +/* vi: ts=8 sts=4 sw=4 + + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen +*/ + +#include "repo.h" + +#include + +#include +#include + +#include + +Repository::Repository() +{ + head_time = (unsigned)-1; +} + +Repository::~Repository() +{ +} + +void Repository::add(const QByteArray &key, Data_entry &data) +{ + RepoIterator it = repo.find(key); + if (it != repo.end()) { + remove(key); + } + if (data.timeout == 0) { + data.timeout = (unsigned)-1; + } else { + data.timeout += time(nullptr); + } + head_time = qMin(head_time, data.timeout); + repo.insert(key, data); +} + +int Repository::remove(const QByteArray &key) +{ + if (key.isEmpty()) { + return -1; + } + + RepoIterator it = repo.find(key); + if (it == repo.end()) { + return -1; + } + it.value().value.fill('x'); + it.value().group.fill('x'); + repo.erase(it); + return 0; +} + +int Repository::removeSpecialKey(const QByteArray &key) +{ + int found = -1; + if (!key.isEmpty()) { + QStack rm_keys; + for (RepoCIterator it = repo.constBegin(); it != repo.constEnd(); ++it) { + if (key.indexOf(it.value().group) == 0 && it.key().indexOf(key) >= 0) { + rm_keys.push(it.key()); + found = 0; + } + } + while (!rm_keys.isEmpty()) { + qCDebug(KSUD_LOG) << "Removed key: " << rm_keys.top(); + remove(rm_keys.pop()); + } + } + return found; +} + +int Repository::removeGroup(const QByteArray &group) +{ + int found = -1; + if (!group.isEmpty()) { + QStack rm_keys; + for (RepoCIterator it = repo.constBegin(); it != repo.constEnd(); ++it) { + if (it.value().group == group) { + rm_keys.push(it.key()); + found = 0; + } + } + while (!rm_keys.isEmpty()) { + qCDebug(KSUD_LOG) << "Removed key: " << rm_keys.top(); + remove(rm_keys.pop()); + } + } + return found; +} + +int Repository::hasGroup(const QByteArray &group) const +{ + if (!group.isEmpty()) { + RepoCIterator it; + for (it = repo.begin(); it != repo.end(); ++it) { + if (it.value().group == group) { + return 0; + } + } + } + return -1; +} + +QByteArray Repository::findKeys(const QByteArray &group, const char *sep) const +{ + QByteArray list = ""; + if (!group.isEmpty()) { + qCDebug(KSUD_LOG) << "Looking for matching key with group key: " << group; + int pos; + QByteArray key; + RepoCIterator it; + for (it = repo.begin(); it != repo.end(); ++it) { + if (it.value().group == group) { + key = it.key(); + qCDebug(KSUD_LOG) << "Matching key found: " << key; + pos = key.lastIndexOf(sep); + key.truncate(pos); + key.remove(0, 2); + if (!list.isEmpty()) { + // Add the same keys only once please :) + if (!list.contains(key)) { + qCDebug(KSUD_LOG) << "Key added to list: " << key; + list += '\007'; // I do not know + list.append(key); + } + } else { + list = key; + } + } + } + } + return list; +} + +QByteArray Repository::find(const QByteArray &key) const +{ + if (key.isEmpty()) { + return nullptr; + } + + RepoCIterator it = repo.find(key); + if (it == repo.end()) { + return nullptr; + } + return it.value().value; +} + +int Repository::expire() +{ + unsigned current = time(nullptr); + if (current < head_time) { + return 0; + } + + unsigned t; + QStack keys; + head_time = (unsigned)-1; + RepoIterator it; + for (it = repo.begin(); it != repo.end(); ++it) { + t = it.value().timeout; + if (t <= current) { + keys.push(it.key()); + } else { + head_time = qMin(head_time, t); + } + } + + int n = keys.count(); + while (!keys.isEmpty()) { + remove(keys.pop()); + } + return n; +} diff --git a/src/kdesud/repo.h b/src/kdesud/repo.h new file mode 100644 index 0000000..3a4eb2d --- /dev/null +++ b/src/kdesud/repo.h @@ -0,0 +1,64 @@ +/* vi: ts=8 sts=4 sw=4 + + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen +*/ + +#ifndef __Repo_h_included__ +#define __Repo_h_included__ + +#include +#include + +/** + * Used internally. + */ +struct Data_entry { + QByteArray value; + QByteArray group; + unsigned int timeout; +}; + +/** + * String repository. + * + * This class implements a string repository with expiration. + */ +class Repository +{ +public: + Repository(); + ~Repository(); + + /** Remove data elements which are expired. */ + int expire(); + + /** Add a data element */ + void add(const QByteArray &key, Data_entry &data); + + /** Delete a data element. */ + int remove(const QByteArray &key); + + /** Delete all data entries having the given group. */ + int removeGroup(const QByteArray &group); + + /** Delete all data entries based on key. */ + int removeSpecialKey(const QByteArray &key); + + /** Checks for the existence of the specified group. */ + int hasGroup(const QByteArray &group) const; + + /** Return a data value. */ + QByteArray find(const QByteArray &key) const; + + /** Returns the key values for the given group. */ + QByteArray findKeys(const QByteArray &group, const char *sep = "-") const; + +private: + QMap repo; + typedef QMap::Iterator RepoIterator; + typedef QMap::ConstIterator RepoCIterator; + unsigned head_time; +}; + +#endif diff --git a/src/kdesud/secure.cpp b/src/kdesud/secure.cpp new file mode 100644 index 0000000..bbb6ebf --- /dev/null +++ b/src/kdesud/secure.cpp @@ -0,0 +1,108 @@ +/* vi: ts=8 sts=4 sw=4 + * + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + secure.cpp: Peer credentials for a UNIX socket. +*/ + +#include "secure.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include + +// FIXME: This is just here to make it compile (since ksock* was removed from kdelibs). +// It would be better to fix it more globally. (Caleb Tennis) +typedef unsigned ksocklen_t; + +/** + * Under Linux, Socket_security is supported. + */ + +#if HAVE_GETPEEREID + +SocketSecurity::SocketSecurity(int sockfd) + : pid(-1) + , gid(-1) + , uid(-1) +{ + uid_t euid; + gid_t egid; + if (getpeereid(sockfd, &euid, &egid) == 0) { + uid = euid; + gid = egid; + pid = -1; + } +} + +#elif HAVE_GETPEERUCRED + +#include + +SocketSecurity::SocketSecurity(int sockfd) + : pid(-1) + , gid(-1) + , uid(-1) +{ + ucred_t *ucred = 0; + + if (getpeerucred(sockfd, &ucred) == 0) { + uid = ucred_geteuid(ucred); + gid = ucred_getrgid(ucred); + pid = -1; + ucred_free(ucred); + } +} + +#elif defined(SO_PEERCRED) + +SocketSecurity::SocketSecurity(int sockfd) + : pid(-1) + , gid(-1) + , uid(-1) +{ + ucred cred; + ksocklen_t len = sizeof(struct ucred); + if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &len) < 0) { + qCCritical(KSUD_LOG) << "getsockopt(SO_PEERCRED) " << strerror(errno); + return; + } + pid = cred.pid; + gid = cred.gid; + uid = cred.uid; +} + +#else +#ifdef __GNUC__ +#warning SocketSecurity support for your platform not implemented/available! +#endif +/** + * The default version does nothing. + */ + +SocketSecurity::SocketSecurity(int sockfd) + : pid(-1) + , gid(-1) + , uid(-1) +{ + static bool warned_him = false; + + if (!warned_him) { + qCWarning(KSUD_LOG) << "Using void socket security. Please add support for your"; + qCWarning(KSUD_LOG) << "platform to src/kdesud/secure.cpp"; + warned_him = true; + } + + // This passes the test made in handler.cpp + uid = getuid(); +} + +#endif diff --git a/src/kdesud/secure.h b/src/kdesud/secure.h new file mode 100644 index 0000000..07e5327 --- /dev/null +++ b/src/kdesud/secure.h @@ -0,0 +1,48 @@ +/* vi: ts=8 sts=4 sw=4 + + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen +*/ + +#ifndef __Secure_h_included__ +#define __Secure_h_included__ + +#include +#include + +/** + * The Socket_security class authenticates the peer for you. It provides + * the process-id, user-id and group-id plus the MD5 sum of the connected + * binary. + */ + +class SocketSecurity +{ +public: + explicit SocketSecurity(int fd); + + /** Returns the peer's process-id. */ + int peerPid() const + { + return pid; + } + + /** Returns the peer's user-id */ + int peerUid() const + { + return uid; + } + + /** Returns the peer's group-id */ + int peerGid() const + { + return gid; + } + +private: + int pid; + int gid; + int uid; +}; + +#endif diff --git a/src/process.h b/src/process.h new file mode 100644 index 0000000..3871e60 --- /dev/null +++ b/src/process.h @@ -0,0 +1,2 @@ +// KDE4 compat header +#include "ptyprocess.h" diff --git a/src/ptyprocess.cpp b/src/ptyprocess.cpp new file mode 100644 index 0000000..c94acf5 --- /dev/null +++ b/src/ptyprocess.cpp @@ -0,0 +1,521 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + This file contains code from TEShell.C of the KDE konsole. + SPDX-FileCopyrightText: 1997, 1998 Lars Doelle + + SPDX-License-Identifier: GPL-2.0-only + + process.cpp: Functionality to build a front end to password asking terminal programs. +*/ + +#include "ptyprocess.h" +#include "kcookie_p.h" +#include "ptyprocess_p.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if HAVE_SYS_SELECT_H +#include // Needed on some systems. +#endif + +#include +#include + +#include +#include + +extern int kdesuDebugArea(); + +namespace KDESu +{ +using namespace KDESuPrivate; + +/* +** Wait for @p ms milliseconds +** @param fd file descriptor +** @param ms time to wait in milliseconds +** @return +*/ +int PtyProcess::waitMS(int fd, int ms) +{ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 1000 * ms; + + fd_set fds; + FD_ZERO(&fds); + FD_SET(fd, &fds); + return select(fd + 1, &fds, nullptr, nullptr, &tv); +} + +// XXX this function is nonsense: +// - for our child, we could use waitpid(). +// - the configurability at this place it *complete* braindamage +/* +** Basic check for the existence of @p pid. +** Returns true iff @p pid is an extant process. +*/ +bool PtyProcess::checkPid(pid_t pid) +{ + KSharedConfig::Ptr config = KSharedConfig::openConfig(); + KConfigGroup cg(config, "super-user-command"); + QString superUserCommand = cg.readEntry("super-user-command", "sudo"); + // sudo does not accept signals from user so we except it + if (superUserCommand == QLatin1String("sudo")) { + return true; + } else { + return kill(pid, 0) == 0; + } +} + +/* +** Check process exit status for process @p pid. +** On error (no child, no exit), return Error (-1). +** If child @p pid has exited, return its exit status, +** (which may be zero). +** If child @p has not exited, return NotExited (-2). +*/ +int PtyProcess::checkPidExited(pid_t pid) +{ + int state; + int ret; + ret = waitpid(pid, &state, WNOHANG); + + if (ret < 0) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "waitpid():" << strerror(errno); + return Error; + } + if (ret == pid) { + if (WIFEXITED(state)) { + return WEXITSTATUS(state); + } + + return Killed; + } + + return NotExited; +} + +PtyProcess::PtyProcess() + : PtyProcess(*new PtyProcessPrivate) +{ +} + +PtyProcess::PtyProcess(PtyProcessPrivate &dd) + : d(&dd) +{ + m_terminal = false; + m_erase = false; +} + +PtyProcess::~PtyProcess() = default; + +int PtyProcess::init() +{ + delete d->pty; + d->pty = new KPty(); + if (!d->pty->open()) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "Failed to open PTY."; + return -1; + } + d->inputBuffer.resize(0); + return 0; +} + +/** Set additional environment variables. */ +void PtyProcess::setEnvironment(const QList &env) +{ + d->env = env; +} + +int PtyProcess::fd() const +{ + return d->pty ? d->pty->masterFd() : -1; +} + +int PtyProcess::pid() const +{ + return m_pid; +} + +/** Returns the additional environment variables set by setEnvironment() */ +QList PtyProcess::environment() const +{ + return d->env; +} + +QByteArray PtyProcess::readAll(bool block) +{ + QByteArray ret; + if (!d->inputBuffer.isEmpty()) { + // if there is still something in the buffer, we need not block. + // we should still try to read any further output, from the fd, though. + block = false; + ret = d->inputBuffer; + d->inputBuffer.resize(0); + } + + int flags = fcntl(fd(), F_GETFL); + if (flags < 0) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "fcntl(F_GETFL):" << strerror(errno); + return ret; + } + int oflags = flags; + if (block) { + flags &= ~O_NONBLOCK; + } else { + flags |= O_NONBLOCK; + } + + if ((flags != oflags) && (fcntl(fd(), F_SETFL, flags) < 0)) { + // We get an error here when the child process has closed + // the file descriptor already. + return ret; + } + + while (1) { + ret.reserve(ret.size() + 0x8000); + int nbytes = read(fd(), ret.data() + ret.size(), 0x8000); + if (nbytes == -1) { + if (errno == EINTR) { + continue; + } else { + break; + } + } + if (nbytes == 0) { + break; // nothing available / eof + } + + ret.resize(ret.size() + nbytes); + break; + } + + return ret; +} + +QByteArray PtyProcess::readLine(bool block) +{ + d->inputBuffer = readAll(block); + + int pos; + QByteArray ret; + if (!d->inputBuffer.isEmpty()) { + pos = d->inputBuffer.indexOf('\n'); + if (pos == -1) { + // NOTE: this means we return something even if there in no full line! + ret = d->inputBuffer; + d->inputBuffer.resize(0); + } else { + ret = d->inputBuffer.left(pos); + d->inputBuffer.remove(0, pos + 1); + } + } + + return ret; +} + +void PtyProcess::writeLine(const QByteArray &line, bool addnl) +{ + if (!line.isEmpty()) { + write(fd(), line.constData(), line.length()); + } + if (addnl) { + write(fd(), "\n", 1); + } +} + +void PtyProcess::unreadLine(const QByteArray &line, bool addnl) +{ + QByteArray tmp = line; + if (addnl) { + tmp += '\n'; + } + if (!tmp.isEmpty()) { + d->inputBuffer.prepend(tmp); + } +} + +void PtyProcess::setExitString(const QByteArray &exit) +{ + m_exitString = exit; +} + +/* + * Fork and execute the command. This returns in the parent. + */ +int PtyProcess::exec(const QByteArray &command, const QList &args) +{ + int i; + + if (init() < 0) { + return -1; + } + + if ((m_pid = fork()) == -1) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "fork():" << strerror(errno); + return -1; + } + + // Parent + if (m_pid) { + d->pty->closeSlave(); + return 0; + } + + // Child + if (setupTTY() < 0) { + _exit(1); + } + + for (const QByteArray &var : std::as_const(d->env)) { + putenv(const_cast(var.constData())); + } + unsetenv("KDE_FULL_SESSION"); + // for : Qt: Session management error + unsetenv("SESSION_MANAGER"); + // QMutex::lock , deadlocks without that. + // you cannot connect to the user's session bus from another UID + unsetenv("DBUS_SESSION_BUS_ADDRESS"); + + // set temporarily LC_ALL to C, for su (to be able to parse "Password:") + const QByteArray old_lc_all = qgetenv("LC_ALL"); + if (!old_lc_all.isEmpty()) { + qputenv("KDESU_LC_ALL", old_lc_all); + } else { + unsetenv("KDESU_LC_ALL"); + } + qputenv("LC_ALL", "C"); + + // From now on, terminal output goes through the tty. + + QByteArray path; + if (command.contains('/')) { + path = command; + } else { + QString file = QStandardPaths::findExecutable(QFile::decodeName(command)); + if (file.isEmpty()) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " << command << "not found."; + _exit(1); + } + path = QFile::encodeName(file); + } + + const char **argp = (const char **)malloc((args.count() + 2) * sizeof(char *)); + + i = 0; + argp[i++] = path.constData(); + for (const QByteArray &arg : args) { + argp[i++] = arg.constData(); + } + + argp[i] = nullptr; + + execv(path.constData(), const_cast(argp)); + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "execv(" << path << "):" << strerror(errno); + _exit(1); + return -1; // Shut up compiler. Never reached. +} + +/* + * Wait until the terminal is set into no echo mode. At least one su + * (RH6 w/ Linux-PAM patches) sets noecho mode AFTER writing the Password: + * prompt, using TCSAFLUSH. This flushes the terminal I/O queues, possibly + * taking the password with it. So we wait until no echo mode is set + * before writing the password. + * Note that this is done on the slave fd. While Linux allows tcgetattr() on + * the master side, Solaris doesn't. + */ +int PtyProcess::waitSlave() +{ + struct termios tio; + while (1) { + if (!checkPid(m_pid)) { + qCCritical(KSU_LOG) << "process has exited while waiting for password."; + return -1; + } + if (!d->pty->tcGetAttr(&tio)) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "tcgetattr():" << strerror(errno); + return -1; + } + if (tio.c_lflag & ECHO) { + // qDebug() << "[" << __FILE__ << ":" << __LINE__ << "] " << "Echo mode still on."; + usleep(10000); + continue; + } + break; + } + return 0; +} + +int PtyProcess::enableLocalEcho(bool enable) +{ + return d->pty->setEcho(enable) ? 0 : -1; +} + +void PtyProcess::setTerminal(bool terminal) +{ + m_terminal = terminal; +} + +void PtyProcess::setErase(bool erase) +{ + m_erase = erase; +} + +/* + * Copy output to stdout until the child process exits, or a line of output + * matches `m_exitString'. + * We have to use waitpid() to test for exit. Merely waiting for EOF on the + * pty does not work, because the target process may have children still + * attached to the terminal. + */ +int PtyProcess::waitForChild() +{ + fd_set fds; + FD_ZERO(&fds); + QByteArray remainder; + + while (1) { + FD_SET(fd(), &fds); + + // specify timeout to make sure select() does not block, even if the + // process is dead / non-responsive. It does not matter if we abort too + // early. In that case 0 is returned, and we'll try again in the next + // iteration. (As long as we don't consistently time out in each iteration) + timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + int ret = select(fd() + 1, &fds, nullptr, nullptr, &timeout); + if (ret == -1) { + if (errno != EINTR) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "select():" << strerror(errno); + return -1; + } + ret = 0; + } + + if (ret) { + for (;;) { + QByteArray output = readAll(false); + if (output.isEmpty()) { + break; + } + if (m_terminal) { + fwrite(output.constData(), output.size(), 1, stdout); + fflush(stdout); + } + if (!m_exitString.isEmpty()) { + // match exit string only at line starts + remainder += output; + while (remainder.length() >= m_exitString.length()) { + if (remainder.startsWith(m_exitString)) { + kill(m_pid, SIGTERM); + remainder.remove(0, m_exitString.length()); + } + int off = remainder.indexOf('\n'); + if (off < 0) { + break; + } + remainder.remove(0, off + 1); + } + } + } + } + + ret = checkPidExited(m_pid); + if (ret == Error) { + if (errno == ECHILD) { + return 0; + } else { + return 1; + } + } else if (ret == Killed) { + return 0; + } else if (ret == NotExited) { + continue; // keep checking + } else { + return ret; + } + } +} + +/* + * SetupTTY: Creates a new session. The filedescriptor "fd" should be + * connected to the tty. It is closed after the tty is reopened to make it + * our controlling terminal. This way the tty is always opened at least once + * so we'll never get EIO when reading from it. + */ +int PtyProcess::setupTTY() +{ + // Reset signal handlers + for (int sig = 1; sig < NSIG; sig++) { + signal(sig, SIG_DFL); + } + signal(SIGHUP, SIG_IGN); + + d->pty->setCTty(); + + // Connect stdin, stdout and stderr + int slave = d->pty->slaveFd(); + dup2(slave, 0); + dup2(slave, 1); + dup2(slave, 2); + + // Close all file handles + // XXX this caused problems in KProcess - not sure why anymore. -- ??? + // Because it will close the start notification pipe. -- ossi + struct rlimit rlp; + getrlimit(RLIMIT_NOFILE, &rlp); + for (int i = 3; i < (int)rlp.rlim_cur; i++) { + close(i); + } + + // Disable OPOST processing. Otherwise, '\n' are (on Linux at least) + // translated to '\r\n'. + struct ::termios tio; + if (tcgetattr(0, &tio) < 0) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "tcgetattr():" << strerror(errno); + return -1; + } + tio.c_oflag &= ~OPOST; + if (tcsetattr(0, TCSANOW, &tio) < 0) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "tcsetattr():" << strerror(errno); + return -1; + } + + return 0; +} + +void PtyProcess::virtual_hook(int id, void *data) +{ + Q_UNUSED(id); + Q_UNUSED(data); + /*BASE::virtual_hook( id, data );*/ +} + +} // namespace KDESu diff --git a/src/ptyprocess.h b/src/ptyprocess.h new file mode 100644 index 0000000..2b6b9d7 --- /dev/null +++ b/src/ptyprocess.h @@ -0,0 +1,214 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + SPDX-License-Identifier: GPL-2.0-only +*/ + +#ifndef KDESUPTYPROCESS_H +#define KDESUPTYPROCESS_H + +#include +#include + +#include +#include +#include +#include + +#include + +#include + +namespace KDESu +{ +class PtyProcessPrivate; + +/** \class PtyProcess ptyprocess.h KDESu/PtyProcess + * Synchronous communication with tty programs. + * + * PtyProcess provides synchronous communication with tty based programs. + * The communications channel used is a pseudo tty (as opposed to a pipe) + * This means that programs which require a terminal will work. + */ + +class KDESU_EXPORT PtyProcess +{ +public: + /** Error return values for checkPidExited() */ + enum checkPidStatus { + Error = -1, /**< No child */ + NotExited = -2, /**< Child hasn't exited */ + Killed = -3, /**< Child terminated by signal */ + }; + + PtyProcess(); + virtual ~PtyProcess(); + + /** + * Forks off and execute a command. The command's standard in and output + * are connected to the pseudo tty. They are accessible with readLine + * and writeLine. + * @param command The command to execute. + * @param args The arguments to the command. + * @return 0 on success, -1 on error. errno might give more information then. + */ + int exec(const QByteArray &command, const QList &args); + + /** + * Reads a line from the program's standard out. Depending on the @em block + * parameter, this call blocks until something was read. + * Note that in some situations this function will return less than a full + * line of output, but never more. Newline characters are stripped. + * @param block Block until a full line is read? + * @return The output string. + */ + QByteArray readLine(bool block = true); + + /** + * Read all available output from the program's standard out. + * @param block If no output is in the buffer, should the function block + * (else it will return an empty QByteArray)? + * @return The output. + */ + QByteArray readAll(bool block = true); + + /** + * Writes a line of text to the program's standard in. + * @param line The text to write. + * @param addNewline Adds a '\n' to the line. + */ + void writeLine(const QByteArray &line, bool addNewline = true); + + /** + * Puts back a line of input. + * @param line The line to put back. + * @param addNewline Adds a '\n' to the line. + */ + void unreadLine(const QByteArray &line, bool addNewline = true); + + /** + * Sets the exit string. If a line of program output matches this, + * waitForChild() will terminate the program and return. + */ + void setExitString(const QByteArray &exit); + + /** + * Waits for the child to exit. See also setExitString. + */ + int waitForChild(); + + /** + * Waits until the pty has cleared the ECHO flag. This is useful + * when programs write a password prompt before they disable ECHO. + * Disabling it might flush any input that was written. + */ + int waitSlave(); + +#if KDESU_ENABLE_DEPRECATED_SINCE(5, 0) + /** + * @deprecated since 5.0, use waitSlave() + */ + KDESU_DEPRECATED_VERSION(5, 0, "Use PtyProcess::waitSlave()") + int WaitSlave() + { + return waitSlave(); + } +#endif + + /** + * Enables/disables local echo on the pseudo tty. + */ + int enableLocalEcho(bool enable = true); + + /** + * Enables/disables terminal output. Relevant only to some subclasses. + */ + void setTerminal(bool terminal); + + /** + * Overwrites the password as soon as it is used. Relevant only to + * some subclasses. + */ + void setErase(bool erase); + + /** + * Set additinal environment variables. + */ + void setEnvironment(const QList &env); + + /** + * Returns the filedescriptor of the process. + */ + int fd() const; + + /** + * Returns the pid of the process. + */ + int pid() const; + + /* + ** This is a collection of static functions that can be + ** used for process control inside kdesu. I'd suggest + ** against using this publicly. There are probably + ** nicer Qt based ways to do what you want. + */ + + /** + ** Wait @p ms milliseconds (ie. 1/10th of a second is 100ms), + ** using @p fd as a filedescriptor to wait on. Returns + ** select(2)'s result, which is -1 on error, 0 on timeout, + ** or positive if there is data on one of the selected fd's. + ** + ** @p ms must be in the range 0..999 (i.e. the maximum wait + ** duration is 999ms, almost one second). + */ + static int waitMS(int fd, int ms); + + /** + ** Basic check for the existence of @p pid. + ** Returns true iff @p pid is an extant process, + ** (one you could kill - see man kill(2) for signal 0). + */ + static bool checkPid(pid_t pid); + + /** + ** Check process exit status for process @p pid. + ** If child @p pid has exited, return its exit status, + ** (which may be zero). + ** On error (no child, no exit), return -1. + ** If child @p has not exited, return -2. + */ + static int checkPidExited(pid_t pid); + +protected: + explicit PtyProcess(PtyProcessPrivate &dd); + + /** Standard hack to add virtual methods in a BC way. Unused. */ + virtual void virtual_hook(int id, void *data); + QList environment() const; + + // KF6 TODO: move to PtyProcessPrivate + bool m_erase; /**< @see setErase() */ + bool m_terminal; /**< Indicates running in a terminal, causes additional + newlines to be printed after output. Set to @c false + in constructor. @see setTerminal() */ + int m_pid; /**< PID of child process */ + QByteArray m_command; /**< Unused */ + QByteArray m_exitString; /**< String to scan for in output that indicates child has exited. */ + +private: + int init(); + int setupTTY(); + +private: + friend class StubProcess; + friend class SshProcess; + friend class SuProcess; + std::unique_ptr const d; + // KF6 TODO: change private d to protected d_ptr, use normal Q_DECLARE_PRIVATE, remove friend +}; + +} + +#endif // KDESUPTYPROCESS_H diff --git a/src/ptyprocess_p.h b/src/ptyprocess_p.h new file mode 100644 index 0000000..f49afee --- /dev/null +++ b/src/ptyprocess_p.h @@ -0,0 +1,37 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + SPDX-FileCopyrightText: 1997, 1998 Lars Doelle + + SPDX-License-Identifier: GPL-2.0-only +*/ + +#ifndef KDESUPTYPROCESS_P_H +#define KDESUPTYPROCESS_P_H + +#include + +#include +#include + +namespace KDESu +{ +class PtyProcessPrivate +{ +public: + PtyProcessPrivate() + { + } + virtual ~PtyProcessPrivate() + { + delete pty; + } + + QList env; + KPty *pty = nullptr; + QByteArray inputBuffer; +}; + +} + +#endif diff --git a/src/ssh.h b/src/ssh.h new file mode 100644 index 0000000..0e906ff --- /dev/null +++ b/src/ssh.h @@ -0,0 +1,2 @@ +// KDE4 compat header +#include "sshprocess.h" diff --git a/src/sshprocess.cpp b/src/sshprocess.cpp new file mode 100644 index 0000000..e5fdd43 --- /dev/null +++ b/src/sshprocess.cpp @@ -0,0 +1,249 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 2000 Geert Jansen + + SPDX-License-Identifier: GPL-2.0-only + + ssh.cpp: Execute a program on a remote machine using ssh. +*/ + +#include "sshprocess.h" + +#include "kcookie_p.h" +#include "stubprocess_p.h" +#include + +#include +#include +#include + +extern int kdesuDebugArea(); + +namespace KDESu +{ +using namespace KDESuPrivate; + +class SshProcessPrivate : public StubProcessPrivate +{ +public: + SshProcessPrivate(const QByteArray &host) + : host(host) + , stub("kdesu_stub") + { + } + QByteArray prompt; + QByteArray host; + QByteArray error; + QByteArray stub; +}; + +SshProcess::SshProcess(const QByteArray &host, const QByteArray &user, const QByteArray &command) + : StubProcess(*new SshProcessPrivate(host)) +{ + m_user = user; + m_command = command; + srand(time(nullptr)); +} + +SshProcess::~SshProcess() = default; + +void SshProcess::setHost(const QByteArray &host) +{ + Q_D(SshProcess); + + d->host = host; +} + +void SshProcess::setStub(const QByteArray &stub) +{ + Q_D(SshProcess); + + d->stub = stub; +} + +int SshProcess::checkInstall(const char *password) +{ + return exec(password, 1); +} + +int SshProcess::checkNeedPassword() +{ + return exec(nullptr, 2); +} + +int SshProcess::exec(const char *password, int check) +{ + Q_D(SshProcess); + + if (check) { + setTerminal(true); + } + + QList args; + args += "-l"; + args += m_user; + args += "-o"; + args += "StrictHostKeyChecking=no"; + args += d->host; + args += d->stub; + + if (StubProcess::exec("ssh", args) < 0) { + return check ? SshNotFound : -1; + } + + int ret = converseSsh(password, check); + if (ret < 0) { + if (!check) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "Conversation with ssh failed."; + } + return ret; + } + if (check == 2) { + if (ret == 1) { + kill(m_pid, SIGTERM); + waitForChild(); + } + return ret; + } + + if (m_erase && password) { + memset(const_cast(password), 0, qstrlen(password)); + } + + ret = converseStub(check); + if (ret < 0) { + if (!check) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "Conversation with kdesu_stub failed."; + } + return ret; + } else if (ret == 1) { + kill(m_pid, SIGTERM); + waitForChild(); + ret = SshIncorrectPassword; + } + + if (check == 1) { + waitForChild(); + return 0; + } + + setExitString("Waiting for forwarded connections to terminate"); + ret = waitForChild(); + return ret; +} + +QByteArray SshProcess::prompt() const +{ + Q_D(const SshProcess); + + return d->prompt; +} + +QByteArray SshProcess::error() const +{ + Q_D(const SshProcess); + + return d->error; +} + +/* + * Conversation with ssh. + * If check is 0, this waits for either a "Password: " prompt, + * or the header of the stub. If a prompt is received, the password is + * written back. Used for running a command. + * If check is 1, operation is the same as 0 except that if a stub header is + * received, the stub is stopped with the "stop" command. This is used for + * checking a password. + * If check is 2, operation is the same as 1, except that no password is + * written. The prompt is saved to prompt. Used for checking the need for + * a password. + */ +int SshProcess::converseSsh(const char *password, int check) +{ + Q_D(SshProcess); + + unsigned i; + unsigned j; + unsigned colon; + + QByteArray line; + int state = 0; + + while (state < 2) { + line = readLine(); + const uint len = line.length(); + if (line.isNull()) { + return -1; + } + + switch (state) { + case 0: + // Check for "kdesu_stub" header. + if (line == "kdesu_stub") { + unreadLine(line); + return 0; + } + + // Match "Password: " with the regex ^[^:]+:[\w]*$. + for (i = 0, j = 0, colon = 0; i < len; ++i) { + if (line[i] == ':') { + j = i; + colon++; + continue; + } + if (!isspace(line[i])) { + j++; + } + } + if ((colon == 1) && (line[j] == ':')) { + if (check == 2) { + d->prompt = line; + return SshNeedsPassword; + } + if (waitSlave()) { + return -1; + } + write(fd(), password, strlen(password)); + write(fd(), "\n", 1); + state++; + break; + } + + // Warning/error message. + d->error += line; + d->error += '\n'; + if (m_terminal) { + fprintf(stderr, "ssh: %s\n", line.constData()); + } + break; + + case 1: + if (line.isEmpty()) { + state++; + break; + } + return -1; + } + } + return 0; +} + +// Display redirection is handled by ssh natively. +QByteArray SshProcess::display() +{ + return "no"; +} + +QByteArray SshProcess::displayAuth() +{ + return "no"; +} + +void SshProcess::virtual_hook(int id, void *data) +{ + StubProcess::virtual_hook(id, data); +} + +} // namespace KDESu diff --git a/src/sshprocess.h b/src/sshprocess.h new file mode 100644 index 0000000..200d178 --- /dev/null +++ b/src/sshprocess.h @@ -0,0 +1,86 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 2000 Geert Jansen + + SPDX-License-Identifier: GPL-2.0-only +*/ + +#ifndef KDESUSSHPROCESS_H +#define KDESUSSHPROCESS_H + +#include "stubprocess.h" + +#include + +namespace KDESu +{ +class SshProcessPrivate; + +/** \class SshProcess sshprocess.h KDESu/SshProcess + * Executes a remote command, using ssh. + */ + +class KDESU_EXPORT SshProcess : public StubProcess +{ +public: + enum Errors { + SshNotFound = 1, + SshNeedsPassword, + SshIncorrectPassword, + }; + + explicit SshProcess(const QByteArray &host = QByteArray(), const QByteArray &user = QByteArray(), const QByteArray &command = QByteArray()); + ~SshProcess() override; + + /** + * Sets the target host. + */ + void setHost(const QByteArray &host); + + /** + * Sets the location of the remote stub. + */ + void setStub(const QByteArray &stub); + + /** + * Checks if the current user\@host needs a password. + * @return The prompt for the password if a password is required. A null + * string otherwise. + * + * @todo The return doc is so obviously wrong that the C code needs to be checked. + */ + int checkNeedPassword(); + + /** + * Checks if the stub is installed and if the password is correct. + * @return Zero if everything is correct, nonzero otherwise. + */ + int checkInstall(const char *password); + + /** + * Executes the command. + */ + int exec(const char *password, int check = 0); + + QByteArray prompt() const; + QByteArray error() const; + +protected: + void virtual_hook(int id, void *data) override; + QByteArray display() override; + QByteArray displayAuth() override; + +private: + int converseSsh(const char *password, int check); + +private: + Q_DECLARE_PRIVATE_D(PtyProcess::d, SshProcess) +#if KDESU_BUILD_DEPRECATED_SINCE(5, 79) + // Unused, kept for ABI compatibility + const void *__kdesu_d_do_not_use; +#endif +}; + +} + +#endif // KDESUSSHPROCESS_H diff --git a/src/stub.h b/src/stub.h new file mode 100644 index 0000000..43948c0 --- /dev/null +++ b/src/stub.h @@ -0,0 +1,2 @@ +// KDE4 compat header +#include "stubprocess.h" diff --git a/src/stubprocess.cpp b/src/stubprocess.cpp new file mode 100644 index 0000000..4b74a81 --- /dev/null +++ b/src/stubprocess.cpp @@ -0,0 +1,253 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + SPDX-License-Identifier: GPL-2.0-only + + stubprocess.cpp: Conversation with kdesu_stub. +*/ + +#include "stubprocess.h" +#include "kcookie_p.h" +#include "stubprocess_p.h" + +#include +#include + +#include + +extern int kdesuDebugArea(); + +namespace KDESu +{ +using namespace KDESuPrivate; + +StubProcess::StubProcess() + : StubProcess(*new StubProcessPrivate) +{ +} + +StubProcess::StubProcess(StubProcessPrivate &dd) + : PtyProcess(dd) +{ + m_user = "root"; + m_scheduler = SchedNormal; + m_priority = 50; + m_cookie = new KCookie; + m_XOnly = true; +} + +StubProcess::~StubProcess() +{ + delete m_cookie; +} + +void StubProcess::setCommand(const QByteArray &command) +{ + m_command = command; +} + +void StubProcess::setUser(const QByteArray &user) +{ + m_user = user; +} + +void StubProcess::setXOnly(bool xonly) +{ + m_XOnly = xonly; +} + +void StubProcess::setPriority(int prio) +{ + if (prio > 100) { + m_priority = 100; + } else if (prio < 0) { + m_priority = 0; + } else { + m_priority = prio; + } +} + +void StubProcess::setScheduler(int sched) +{ + m_scheduler = sched; +} + +QByteArray StubProcess::commaSeparatedList(const QList &lst) +{ + QByteArray str; + for (const auto &ba : lst) { + str += ','; + str += ba; + } + return str; +} + +void StubProcess::writeString(const QByteArray &str) +{ + QByteArray out; + out.reserve(str.size() + 8); + for (const uchar c : str) { + if (c < 32) { + out.append('\\'); + out.append(c + '@'); + } else if (c == '\\') { + out.append('\\'); + out.append('/'); + } else { + out.append(c); + } + } + writeLine(out); +} + +/* + * Map pid_t to a signed integer type that makes sense for QByteArray; + * only the most common sizes 16 bit and 32 bit are special-cased. + */ +template +struct PIDType { + typedef pid_t PID_t; +}; +template<> +struct PIDType<2> { + typedef qint16 PID_t; +}; +template<> +struct PIDType<4> { + typedef qint32 PID_t; +}; + +/* + * Conversation with kdesu_stub. This is how we pass the authentication + * tokens (X11) and other stuff to kdesu_stub. + * return values: -1 = error, 0 = ok, 1 = kill me + */ + +int StubProcess::converseStub(int check) +{ + QByteArray line; + QByteArray tmp; + + while (1) { + line = readLine(); + if (line.isNull()) { + return -1; + } + + if (line == "kdesu_stub") { + // This makes parsing a lot easier. + enableLocalEcho(false); + if (check) { + writeLine("stop"); + } else { + writeLine("ok"); + } + break; + } + } + + while (1) { + line = readLine(); + if (line.isNull()) { + return -1; + } + + if (line == "display") { + writeLine(display()); + } else if (line == "display_auth") { +#if HAVE_X11 + writeLine(displayAuth()); +#else + writeLine(""); +#endif + } else if (line == "command") { + writeString(m_command); + } else if (line == "path") { + QByteArray path = qgetenv("PATH"); + if (!path.isEmpty() && path[0] == ':') { + path = path.mid(1); + } + if (m_user == "root") { + if (!path.isEmpty()) { + path = "/sbin:/bin:/usr/sbin:/usr/bin:" + path; + } else { + path = "/sbin:/bin:/usr/sbin:/usr/bin"; + } + } + writeLine(path); + } else if (line == "user") { + writeLine(m_user); + } else if (line == "priority") { + tmp.setNum(m_priority); + writeLine(tmp); + } else if (line == "scheduler") { + if (m_scheduler == SchedRealtime) { + writeLine("realtime"); + } else { + writeLine("normal"); + } + } else if (line == "xwindows_only") { + if (m_XOnly) { + writeLine("no"); + } else { + writeLine("yes"); + } + } else if (line == "app_startup_id") { + const QList env = environment(); + QByteArray tmp; + static const char startup_env[] = "DESKTOP_STARTUP_ID="; + static const std::size_t size = sizeof(startup_env); + for (const auto &var : env) { + if (var.startsWith(startup_env)) { + tmp = var.mid(size - 1); + } + } + if (tmp.isEmpty()) { + tmp = "0"; // krazy:exclude=doublequote_chars + } + writeLine(tmp); + } else if (line == "app_start_pid") { // obsolete + // Force the pid_t returned from getpid() into + // something QByteArray understands; avoids ambiguity + // between short and unsigned short in particular. + tmp.setNum((PIDType::PID_t)(getpid())); + writeLine(tmp); + } else if (line == "environment") { // additional env vars + const QList env = environment(); + for (const auto &var : env) { + writeString(var); + } + writeLine(""); + } else if (line == "end") { + return 0; + } else { + qCWarning(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "Unknown request:" << line; + return 1; + } + } + + return 0; +} + +QByteArray StubProcess::display() +{ + return m_cookie->display(); +} + +QByteArray StubProcess::displayAuth() +{ +#if HAVE_X11 + return m_cookie->displayAuth(); +#else + return QByteArray(); +#endif +} + +void StubProcess::virtual_hook(int id, void *data) +{ + PtyProcess::virtual_hook(id, data); +} + +} // namespace KDESu diff --git a/src/stubprocess.h b/src/stubprocess.h new file mode 100644 index 0000000..85d1d5a --- /dev/null +++ b/src/stubprocess.h @@ -0,0 +1,118 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + SPDX-License-Identifier: GPL-2.0-only +*/ + +#ifndef KDESUSTUBPROCESS_H +#define KDESUSTUBPROCESS_H + +#include "ptyprocess.h" + +#include + +#include +#include + +namespace KDESu +{ +namespace KDESuPrivate +{ +class KCookie; +} +class StubProcessPrivate; + +/** \class StubProcess stubprocess.h KDESu/StubProcess + * Chat with kdesu_stub. + * + * StubProcess extends PtyProcess with functionality to chat with kdesu_stub. + */ + +class KDESU_EXPORT StubProcess : public PtyProcess +{ +public: + /** + * Different schedulers. SchedNormal is the normal Unix timesharing + * scheduler, while SchedRealtime is a POSIX.1b realtime scheduler. + */ + enum Scheduler { + SchedNormal, + SchedRealtime, + }; + + StubProcess(); + ~StubProcess() override; + + /** + * Set the command. + */ + void setCommand(const QByteArray &command); + + /** + * Set the target user. + */ + void setUser(const QByteArray &user); + + /** + * Set to "X only mode": Sycoca is not built and kdeinit is not launched. + */ + void setXOnly(bool xonly); + + /** + * Set the priority of the process. The priority value must be between 0 + * and 100, 0 being the lowest priority. This value is mapped to the + * scheduler and system dependent priority range of the OS. + */ + void setPriority(int prio); + + /** + * Set the scheduler type. + */ + void setScheduler(int sched); + +protected: + void virtual_hook(int id, void *data) override; + + /** + * Exchange all parameters with kdesu_stub. + */ + int converseStub(int check); + + /** + * This virtual function can be overloaded when special behavior is + * desired. By default, it returns the value returned by KCookie. + */ + virtual QByteArray display(); + + /** + * See display. + */ + virtual QByteArray displayAuth(); + + // KF6 TODO: move to StubProcessPrivate + bool m_XOnly; + int m_priority; + int m_scheduler; + QByteArray m_command; + QByteArray m_user; + KDESuPrivate::KCookie *m_cookie; + +private: + QByteArray commaSeparatedList(const QList &lst); + void writeString(const QByteArray &str); + +protected: + explicit StubProcess(StubProcessPrivate &dd); + +private: + Q_DECLARE_PRIVATE_D(PtyProcess::d, StubProcess) +#if KDESU_BUILD_DEPRECATED_SINCE(5, 79) + // Unused, kept for ABI compatibility + const void *__kdesu_d_do_not_use; +#endif +}; + +} + +#endif // KDESUSTUBPROCESS_H diff --git a/src/stubprocess_p.h b/src/stubprocess_p.h new file mode 100644 index 0000000..4fe90af --- /dev/null +++ b/src/stubprocess_p.h @@ -0,0 +1,21 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + SPDX-License-Identifier: GPL-2.0-only +*/ + +#ifndef KDESUSTUBPROCESS_P_H +#define KDESUSTUBPROCESS_P_H + +#include "ptyprocess_p.h" + +namespace KDESu +{ +class StubProcessPrivate : public PtyProcessPrivate +{ +}; + +} + +#endif diff --git a/src/su.h b/src/su.h new file mode 100644 index 0000000..6796f89 --- /dev/null +++ b/src/su.h @@ -0,0 +1,2 @@ +// KDE4 compat header +#include "suprocess.h" diff --git a/src/suprocess.cpp b/src/suprocess.cpp new file mode 100644 index 0000000..2d569cc --- /dev/null +++ b/src/suprocess.cpp @@ -0,0 +1,307 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + Sudo support added by Jonathan Riddell + SPDX-FileCopyrightText: 2005 Canonical Ltd // krazy:exclude=copyright (no email) + + SPDX-License-Identifier: GPL-2.0-only + + su.cpp: Execute a program as another user with "class SuProcess". +*/ + +#include "suprocess.h" + +#include "kcookie_p.h" +#include "stubprocess_p.h" +#include + +#include +#include +#include + +#include +#include +#include +#include + +#if defined(KDESU_USE_SUDO_DEFAULT) +#define DEFAULT_SUPER_USER_COMMAND QStringLiteral("sudo") +#elif defined(KDESU_USE_DOAS_DEFAULT) +#define DEFAULT_SUPER_USER_COMMAND QStringLiteral("doas") +#else +#define DEFAULT_SUPER_USER_COMMAND QStringLiteral("su") +#endif + +namespace KDESu +{ +using namespace KDESuPrivate; + +class SuProcessPrivate : public StubProcessPrivate +{ +public: + bool isPrivilegeEscalation() const; + QString superUserCommand; +}; + +bool SuProcessPrivate::isPrivilegeEscalation() const +{ + return (superUserCommand == QLatin1String("sudo") || superUserCommand == QLatin1String("doas")); +} + +SuProcess::SuProcess(const QByteArray &user, const QByteArray &command) + : StubProcess(*new SuProcessPrivate) +{ + Q_D(SuProcess); + + m_user = user; + m_command = command; + + KSharedConfig::Ptr config = KSharedConfig::openConfig(); + KConfigGroup group(config, "super-user-command"); + d->superUserCommand = group.readEntry("super-user-command", DEFAULT_SUPER_USER_COMMAND); + + if (!d->isPrivilegeEscalation() && d->superUserCommand != QLatin1String("su")) { + qCWarning(KSU_LOG) << "unknown super user command."; + d->superUserCommand = DEFAULT_SUPER_USER_COMMAND; + } +} + +SuProcess::~SuProcess() = default; + +QString SuProcess::superUserCommand() +{ + Q_D(SuProcess); + + return d->superUserCommand; +} + +bool SuProcess::useUsersOwnPassword() +{ + Q_D(SuProcess); + + if (d->isPrivilegeEscalation() && m_user == "root") { + return true; + } + + KUser user; + return user.loginName() == QString::fromUtf8(m_user); +} + +int SuProcess::checkInstall(const char *password) +{ + return exec(password, Install); +} + +int SuProcess::checkNeedPassword() +{ + return exec(nullptr, NeedPassword); +} + +/* + * Execute a command with su(1). + */ +int SuProcess::exec(const char *password, int check) +{ + Q_D(SuProcess); + + if (check) { + setTerminal(true); + } + + // since user may change after constructor (due to setUser()) + // we need to override sudo with su for non-root here + if (m_user != QByteArray("root")) { + d->superUserCommand = QStringLiteral("su"); + } + + QList args; + if (d->isPrivilegeEscalation()) { + args += "-u"; + } + + if (m_scheduler != SchedNormal || m_priority > 50) { + args += "root"; + } else { + args += m_user; + } + + if (d->superUserCommand == QLatin1String("su")) { + args += "-c"; + } + // Get the kdesu_stub and su command from a config file if set, used in test + KSharedConfig::Ptr config = KSharedConfig::openConfig(); + KConfigGroup group(config, "super-user-command"); + const QString defaultPath = QStringLiteral(KDE_INSTALL_FULL_LIBEXECDIR_KF) + QStringLiteral("/kdesu_stub"); + const QString kdesuStubPath = group.readEntry("kdesu_stub_path", defaultPath); + args += kdesuStubPath.toLocal8Bit(); + args += "-"; // krazy:exclude=doublequote_chars (QList, not QString) + + const QString commandString = group.readEntry("command", QStandardPaths::findExecutable(d->superUserCommand)); + const QByteArray command = commandString.toLocal8Bit(); + if (command.isEmpty()) { + return check ? SuNotFound : -1; + } + + if (StubProcess::exec(command, args) < 0) { + return check ? SuNotFound : -1; + } + + SuErrors ret = (SuErrors)converseSU(password); + + if (ret == error) { + if (!check) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "Conversation with" << d->superUserCommand << "failed."; + } + return ret; + } + if (check == NeedPassword) { + if (ret == killme) { + if (d->isPrivilegeEscalation()) { + // sudo can not be killed, just return + return ret; + } + if (kill(m_pid, SIGKILL) < 0) { + // FIXME SIGKILL doesn't work for sudo, + // why is this different from su? + // A: because sudo runs as root. Perhaps we could write a Ctrl+C to its stdin, instead? + ret = error; + } else { + int iret = waitForChild(); + if (iret < 0) { + ret = error; + } + } + } + return ret; + } + + if (m_erase && password) { + memset(const_cast(password), 0, qstrlen(password)); + } + + if (ret != ok) { + kill(m_pid, SIGKILL); + if (d->isPrivilegeEscalation()) { + waitForChild(); + } + return SuIncorrectPassword; + } + + int iret = converseStub(check); + if (iret < 0) { + if (!check) { + qCCritical(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " + << "Conversation with kdesu_stub failed."; + } + return iret; + } else if (iret == 1) { + kill(m_pid, SIGKILL); + waitForChild(); + return SuIncorrectPassword; + } + + if (check == Install) { + waitForChild(); + return 0; + } + + iret = waitForChild(); + return iret; +} + +/* + * Conversation with su: feed the password. + * Return values: -1 = error, 0 = ok, 1 = kill me, 2 not authorized + */ +int SuProcess::converseSU(const char *password) +{ + enum { + WaitForPrompt, + CheckStar, + HandleStub, + } state = WaitForPrompt; + int colon; + unsigned i; + unsigned j; + + QByteArray line; + while (true) { + line = readLine(); + // return if problem. sudo checks for a second prompt || su gets a blank line + if ((line.contains(':') && state != WaitForPrompt) || line.isNull()) { + return (state == HandleStub ? notauthorized : error); + } + + if (line == "kdesu_stub") { + unreadLine(line); + return ok; + } + + switch (state) { + case WaitForPrompt: { + if (waitMS(fd(), 100) > 0) { + // There is more output available, so this line + // couldn't have been a password prompt (the definition + // of prompt being that there's a line of output followed + // by a colon, and then the process waits). + continue; + } + + const uint len = line.length(); + // Match "Password: " with the regex ^[^:]+:[\w]*$. + for (i = 0, j = 0, colon = 0; i < len; ++i) { + if (line[i] == ':') { + j = i; + colon++; + continue; + } + if (!isspace(line[i])) { + j++; + } + } + if (colon == 1 && line[j] == ':') { + if (password == nullptr) { + return killme; + } + if (waitSlave()) { + return error; + } + write(fd(), password, strlen(password)); + write(fd(), "\n", 1); + state = CheckStar; + } + break; + } + ////////////////////////////////////////////////////////////////////////// + case CheckStar: { + const QByteArray s = line.trimmed(); + if (s.isEmpty()) { + state = HandleStub; + break; + } + const bool starCond = std::any_of(s.cbegin(), s.cend(), [](const char c) { + return c != '*'; + }); + if (starCond) { + return error; + } + state = HandleStub; + break; + } + ////////////////////////////////////////////////////////////////////////// + case HandleStub: + break; + ////////////////////////////////////////////////////////////////////////// + } // end switch + } // end while (true) + return ok; +} + +void SuProcess::virtual_hook(int id, void *data) +{ + StubProcess::virtual_hook(id, data); +} + +} // namespace KDESu diff --git a/src/suprocess.h b/src/suprocess.h new file mode 100644 index 0000000..ec56483 --- /dev/null +++ b/src/suprocess.h @@ -0,0 +1,93 @@ +/* + This file is part of the KDE project, module kdesu. + SPDX-FileCopyrightText: 1999, 2000 Geert Jansen + + SPDX-License-Identifier: GPL-2.0-only +*/ + +#ifndef KDESUSUPROCESS_H +#define KDESUSUPROCESS_H + +#include + +#include "stubprocess.h" + +namespace KDESu +{ +class SuProcessPrivate; + +/** \class SuProcess suprocess.h KDESu/SuProcess + * Executes a command under elevated privileges, using su. + */ + +class KDESU_EXPORT SuProcess : public StubProcess +{ +public: + enum Errors { + SuNotFound = 1, + SuNotAllowed, + SuIncorrectPassword, + }; + + /** + * Executes the command. This will wait for the command to finish. + */ + enum checkMode { + NoCheck = 0, + Install = 1, + NeedPassword = 2, + }; + + explicit SuProcess(const QByteArray &user = nullptr, const QByteArray &command = nullptr); + ~SuProcess() override; + + int exec(const char *password, int check = NoCheck); + + /** + * Checks if the stub is installed and the password is correct. + * @return Zero if everything is correct, nonzero otherwise. + */ + int checkInstall(const char *password); + + /** + * Checks if a password is needed. + */ + int checkNeedPassword(); + + /** + * Checks what the default super user command is, e.g. sudo, su, etc + * @return the default super user command + */ + QString superUserCommand(); + + /** + * Checks whether or not the user's password is being asked for or another + * user's password. Due to usage of systems such as sudo, even when attempting + * to switch to another user one may need to enter their own password. + */ + bool useUsersOwnPassword(); + +protected: + void virtual_hook(int id, void *data) override; + +private: + enum SuErrors { + error = -1, + ok = 0, + killme = 1, + notauthorized = 2, + }; + + int converseSU(const char *password); + +private: + Q_DECLARE_PRIVATE_D(PtyProcess::d, SuProcess) +#if KDESU_BUILD_DEPRECATED_SINCE(5, 79) + // Unused, kept for ABI compatibility + const void *__kdesu_d_do_not_use; +#endif +}; + +} + +#endif // KDESUSUPROCESS_H