├── .gitignore ├── COPYING ├── CREDITS ├── Changelog ├── INSTALL ├── LICENSE ├── Makefile.am ├── README.md ├── autogen.sh ├── configure.ac ├── pixmaps ├── Makefile.am └── ktsuss.png └── src ├── Makefile.am ├── errors.h ├── ktsuss.c ├── su_backend.c ├── su_backend.h ├── sudo_backend.c └── sudo_backend.h /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | Makefile.in 3 | aclocal.m4 4 | autom4te.cache/ 5 | compile 6 | config.h 7 | config.h.in 8 | config.log 9 | config.status 10 | configure 11 | depcomp 12 | install-sh 13 | ltmain.sh 14 | missing 15 | pixmaps/Makefile 16 | pixmaps/Makefile.in 17 | src/.deps/ 18 | src/Makefile 19 | src/Makefile.in 20 | src/ktsuss 21 | stamp-h1 22 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007-2014, David B. Cortarello 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice 8 | and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice 10 | and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | * Neither the name of Kwort nor the names of its contributors may be used 13 | to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | Authors: 2 | ======= 3 | David B. Cortarello (Nomius) 4 | 5 | Contributors: 6 | ============ 7 | Christian Dywan (Christian) 8 | Ren? Neumann (Ren?) 9 | Enrico Tr?ger (Enrico) 10 | Valere Monseur (Valere) 11 | -------------------------------------------------------------------------------- /Changelog: -------------------------------------------------------------------------------- 1 | commit 0bba7349d02b94358c8c156add81263bd4c8ac96 2 | Author: David B. Cortarello 3 | Date: Tue Mar 4 01:21:59 2014 -0300 4 | 5 | Changed homepage 6 | 7 | commit 47d9262defccc351a0b5f408b1c3c9e7bf0c60fc 8 | Author: David B. Cortarello 9 | Date: Tue Mar 4 01:08:25 2014 -0300 10 | 11 | Applied patch by possum@possum.cc. Also ignored stderr and improved return status in password check 12 | 13 | commit 673aff22bdeee66a903c62667c67e91592656a9c 14 | Author: David B. Cortarello 15 | Date: Tue Mar 4 00:27:16 2014 -0300 16 | 17 | Fixed issue provoked by SIGHUP received by the new forked pty 18 | 19 | commit 9818286fafc454c89ab8fda9db1700ac97bdfd52 20 | Author: nomius 21 | Date: Sun Feb 16 03:19:25 2014 -0200 22 | 23 | Removed old README file 24 | 25 | commit 4b400abb918f4a2997f497c5f6aa5d0b32da06ac 26 | Merge: 47e6a39 aeb7b4d 27 | Author: David B. Cortarello 28 | Date: Sun Feb 16 02:12:24 2014 -0300 29 | 30 | Merge branch 'master' of github.com:nomius/ktsuss 31 | 32 | commit aeb7b4de8e0b50c76652d2cf8b9f0fd1f4880593 33 | Author: nomius 34 | Date: Sat Feb 15 21:15:09 2014 -0800 35 | 36 | Initial commit 37 | 38 | commit 47e6a391cdbf6e119de5401985d7d4b2904505e4 39 | Author: nomius 40 | Date: Wed Jan 30 03:08:13 2013 +0000 41 | 42 | I'm commiting this patch by Franck Endres, but I'm not completely sure if making a login shell would be what everyone would like. So I'll push this patch and I'll let people test before version bump 43 | 44 | commit e6a2efe0209cf1f22962fea2454c3871c8394f52 45 | Author: nomius 46 | Date: Wed Nov 9 01:40:37 2011 +0000 47 | 48 | Updated Changelog 49 | 50 | commit 18e1ecfa14bf6909a8ff7148ecfaca5a24e2addc 51 | Author: nomius 52 | Date: Tue Nov 8 23:57:22 2011 +0000 53 | 54 | Change the main window tittle according to the command given 55 | 56 | commit 7bd45d9b7c3d0006eba7f657be44d389d1eab067 57 | Author: nomius 58 | Date: Tue Nov 8 23:52:21 2011 +0000 59 | 60 | Implemented sudo backend 61 | 62 | commit 338c357ea7a0b4a75be8006f9ee3779c3bc65c36 63 | Author: nomius 64 | Date: Tue Nov 8 05:21:29 2011 +0000 65 | 66 | su backend fixed 67 | 68 | commit a77c93cc8844371e2efed4541c1dea1d24f66ee4 69 | Author: nomius 70 | Date: Mon Aug 15 22:20:55 2011 +0000 71 | 72 | I don't like the idea of having a Changelog versioned , but since ktsuss changed like 3 times repositories it's a good way to keep up the old history 73 | 74 | commit 482dd0b43a27fac1623a273d8bd9efc47cfb650a 75 | Author: nomius 76 | Date: Sun Jun 26 22:42:39 2011 +0000 77 | 78 | Added Valere to the credits because to his bug fix 79 | 80 | commit 7d3af214b191d94b4c2f9b8f7bbe1424ddd25feb 81 | Author: nomius 82 | Date: Sun Jun 26 22:40:12 2011 +0000 83 | 84 | Fixed bug with commands with more than one parameter 85 | 86 | commit 41bbbd7ecc0f62b79d3fb0e44cb0d34ffb636c98 87 | Author: nomius 88 | Date: Mon Mar 28 13:56:00 2011 +0000 89 | 90 | Initial code version 91 | 92 | commit 2e276fb47e7f8b3e1abb5ed2e3d0b69f786705f1 93 | Author: nomius 94 | Date: Mon Mar 28 13:54:00 2011 +0000 95 | 96 | Initial repository structure 97 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Basic Installation 2 | ================== 3 | 4 | These are generic installation instructions. 5 | 6 | The `configure' shell script attempts to guess correct values for 7 | various system-dependent variables used during compilation. It uses 8 | those values to create a `Makefile' in each directory of the package. 9 | It may also create one or more `.h' files containing system-dependent 10 | definitions. Finally, it creates a shell script `config.status' that 11 | you can run in the future to recreate the current configuration, a file 12 | `config.cache' that saves the results of its tests to speed up 13 | reconfiguring, and a file `config.log' containing compiler output 14 | (useful mainly for debugging `configure'). 15 | 16 | If you need to do unusual things to compile the package, please try 17 | to figure out how `configure' could check whether to do them, and mail 18 | diffs or instructions to the address given in the `README' so they can 19 | be considered for the next release. If at some point `config.cache' 20 | contains results you don't want to keep, you may remove or edit it. 21 | 22 | The file `configure.in' is used to create `configure' by a program 23 | called `autoconf'. You only need `configure.in' if you want to change 24 | it or regenerate `configure' using a newer version of `autoconf'. 25 | 26 | The simplest way to compile this package is: 27 | 28 | 1. `cd' to the directory containing the package's source code and type 29 | `./configure' to configure the package for your system. If you're 30 | using `csh' on an old version of System V, you might need to type 31 | `sh ./configure' instead to prevent `csh' from trying to execute 32 | `configure' itself. 33 | 34 | Running `configure' takes awhile. While running, it prints some 35 | messages telling which features it is checking for. 36 | 37 | 2. Type `make' to compile the package. 38 | 39 | 3. Optionally, type `make check' to run any self-tests that come with 40 | the package. 41 | 42 | 4. Type `make install' to install the programs and any data files and 43 | documentation. 44 | 45 | 5. You can remove the program binaries and object files from the 46 | source code directory by typing `make clean'. To also remove the 47 | files that `configure' created (so you can compile the package for 48 | a different kind of computer), type `make distclean'. There is 49 | also a `make maintainer-clean' target, but that is intended mainly 50 | for the package's developers. If you use it, you may have to get 51 | all sorts of other programs in order to regenerate files that came 52 | with the distribution. 53 | 54 | Compilers and Options 55 | ===================== 56 | 57 | Some systems require unusual options for compilation or linking that 58 | the `configure' script does not know about. You can give `configure' 59 | initial values for variables by setting them in the environment. Using 60 | a Bourne-compatible shell, you can do that on the command line like 61 | this: 62 | CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure 63 | 64 | Or on systems that have the `env' program, you can do it like this: 65 | env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure 66 | 67 | Compiling For Multiple Architectures 68 | ==================================== 69 | 70 | You can compile the package for more than one kind of computer at the 71 | same time, by placing the object files for each architecture in their 72 | own directory. To do this, you must use a version of `make' that 73 | supports the `VPATH' variable, such as GNU `make'. `cd' to the 74 | directory where you want the object files and executables to go and run 75 | the `configure' script. `configure' automatically checks for the 76 | source code in the directory that `configure' is in and in `..'. 77 | 78 | If you have to use a `make' that does not supports the `VPATH' 79 | variable, you have to compile the package for one architecture at a time 80 | in the source code directory. After you have installed the package for 81 | one architecture, use `make distclean' before reconfiguring for another 82 | architecture. 83 | 84 | Installation Names 85 | ================== 86 | 87 | By default, `make install' will install the package's files in 88 | `/usr/local/bin', `/usr/local/man', etc. You can specify an 89 | installation prefix other than `/usr/local' by giving `configure' the 90 | option `--prefix=PATH'. 91 | 92 | You can specify separate installation prefixes for 93 | architecture-specific files and architecture-independent files. If you 94 | give `configure' the option `--exec-prefix=PATH', the package will use 95 | PATH as the prefix for installing programs and libraries. 96 | Documentation and other data files will still use the regular prefix. 97 | 98 | In addition, if you use an unusual directory layout you can give 99 | options like `--bindir=PATH' to specify different values for particular 100 | kinds of files. Run `configure --help' for a list of the directories 101 | you can set and what kinds of files go in them. 102 | 103 | If the package supports it, you can cause programs to be installed 104 | with an extra prefix or suffix on their names by giving `configure' the 105 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 106 | 107 | Optional Features 108 | ================= 109 | 110 | Some packages pay attention to `--enable-FEATURE' options to 111 | `configure', where FEATURE indicates an optional part of the package. 112 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 113 | is something like `gnu-as' or `x' (for the X Window System). The 114 | `README' should mention any `--enable-' and `--with-' options that the 115 | package recognizes. 116 | 117 | For packages that use the X Window System, `configure' can usually 118 | find the X include and library files automatically, but if it doesn't, 119 | you can use the `configure' options `--x-includes=DIR' and 120 | `--x-libraries=DIR' to specify their locations. 121 | 122 | Specifying the System Type 123 | ========================== 124 | 125 | There may be some features `configure' can not figure out 126 | automatically, but needs to determine by the type of host the package 127 | will run on. Usually `configure' can figure that out, but if it prints 128 | a message saying it can not guess the host type, give it the 129 | `--host=TYPE' option. TYPE can either be a short name for the system 130 | type, such as `sun4', or a canonical name with three fields: 131 | CPU-COMPANY-SYSTEM 132 | 133 | See the file `config.sub' for the possible values of each field. If 134 | `config.sub' isn't included in this package, then this package doesn't 135 | need to know the host type. 136 | 137 | If you are building compiler tools for cross-compiling, you can also 138 | use the `--target=TYPE' option to select the type of system they will 139 | produce code for and the `--build=TYPE' option to select the type of 140 | system on which you are compiling the package. 141 | 142 | Sharing Defaults 143 | ================ 144 | 145 | If you want to set default values for `configure' scripts to share, 146 | you can create a site shell script called `config.site' that gives 147 | default values for variables like `CC', `cache_file', and `prefix'. 148 | `configure' looks for `PREFIX/share/config.site' if it exists, then 149 | `PREFIX/etc/config.site' if it exists. Or, you can set the 150 | `CONFIG_SITE' environment variable to the location of the site script. 151 | A warning: not all `configure' scripts look for a site script. 152 | 153 | Operation Controls 154 | ================== 155 | 156 | `configure' recognizes the following options to control how it 157 | operates. 158 | 159 | `--cache-file=FILE' 160 | Use and save the results of the tests in FILE instead of 161 | `./config.cache'. Set FILE to `/dev/null' to disable caching, for 162 | debugging `configure'. 163 | 164 | `--help' 165 | Print a summary of the options to `configure', and exit. 166 | 167 | `--quiet' 168 | `--silent' 169 | `-q' 170 | Do not print messages saying which checks are being made. To 171 | suppress all normal output, redirect it to `/dev/null' (any error 172 | messages will still be shown). 173 | 174 | `--srcdir=DIR' 175 | Look for the package's source code in directory DIR. Usually 176 | `configure' can determine that directory automatically. 177 | 178 | `--version' 179 | Print the version of Autoconf used to generate the `configure' 180 | script, and exit. 181 | 182 | `configure' also accepts some other, not widely useful, options. 183 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, nomius 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | CLEANFILES = *~ 2 | 3 | SUBDIRS = src pixmaps 4 | MAINTAINERCLEANFILES = Makefile.in configure aclocal.m4 \ 5 | config.h config.h.in 6 | AUTOMAKE_OPTIONS = foreign dist-bzip2 7 | EXTRA_DIST = autogen.bash AUTHORS Changelog COPYING INSTALL README 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ktsuss 2 | ====== 3 | 4 | ktsuss stands for "keep the su simple, stupid", and as the name says, is a graphical version (frontend) of su written in C and GTK+ 2. The idea of the project is to remain simple and bug free. 5 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # vim: set sw=4 sts=4 et tw=80 : 3 | 4 | run() { 5 | echo ">>> $@" 6 | if ! $@ ; then 7 | echo "oops!" 1>&2 8 | exit 127 9 | fi 10 | } 11 | 12 | get() { 13 | type ${1}-${2} &>/dev/null && echo ${1}-${2} && return 14 | type ${1}${2//.} &>/dev/null && echo ${1}${2//.} && return 15 | type ${1} &>/dev/null && echo ${1} && return 16 | echo "Could not find ${1} ${2}" 1>&2 17 | exit 127 18 | } 19 | 20 | run mkdir -p config 21 | run $(get libtoolize 1.5 ) --copy --force --automake 22 | rm -f config.cache 23 | run $(get aclocal 1.9 ) 24 | run $(get autoheader 2.59 ) 25 | run $(get autoconf 2.59 ) 26 | run $(get automake 1.9 ) -a --copy 27 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl vim: set sw=8 sts=8 noet : 2 | 3 | AC_INIT([ktsuss], [2], [dcortarello@gmail.com]) 4 | AC_PREREQ(2.5) 5 | AM_INIT_AUTOMAKE(1.9) 6 | AC_PROG_CC 7 | AC_CONFIG_HEADER(config.h) 8 | AC_PROG_CC_C_O 9 | dnl check for required programs 10 | AC_PROG_INSTALL 11 | AC_PROG_LN_S 12 | AC_PROG_RANLIB 13 | AC_PROG_MAKE_SET 14 | AC_TYPE_SIZE_T 15 | AC_TYPE_PID_T 16 | AC_C_BIGENDIAN 17 | AC_C_INLINE 18 | AC_CHECK_SIZEOF(int, 32) 19 | PKG_CHECK_MODULES(DEPS, gtk+-2.0 >= 2.2 glib-2.0 >= 2.2) 20 | AC_SUBST(DEPS_CFLAGS) 21 | AC_SUBST(DEPS_LIBS) 22 | AC_ARG_ENABLE([sudo], [ --enable-sudo=yes|no use the sudo backend instead the su one. default no.], [BUILD_SUDO="$enableval"], [BUILD_SUDO=no]) 23 | case $BUILD_SUDO in 24 | no) 25 | AC_MSG_CHECKING([whether we can locate the su program]) 26 | supath=`which su 2>/dev/null` 27 | if test "x$supath" = "x"; then 28 | echo 29 | AC_MSG_ERROR([Could not find su in PATH]) 30 | else 31 | AC_DEFINE_UNQUOTED([SUPATH], "$supath", [su path]) 32 | echo $supath 33 | fi 34 | ;; 35 | yes) 36 | AC_MSG_CHECKING([whether we can locate the sudo program]) 37 | sudopath=`which sudo 2>/dev/null` 38 | if test "x$sudopath" = "x"; then 39 | echo 40 | AC_MSG_ERROR([Could not find sudo in PATH]) 41 | else 42 | AC_DEFINE_UNQUOTED([SUDOPATH], "$sudopath", [sudo path]) 43 | echo $sudopath 44 | fi 45 | ;; 46 | esac 47 | AM_CONDITIONAL(BUILD_WITH_SUDO, test "x$BUILD_SUDO" = "xyes") 48 | 49 | dnl output 50 | AC_OUTPUT( 51 | Makefile 52 | src/Makefile 53 | pixmaps/Makefile 54 | ) 55 | -------------------------------------------------------------------------------- /pixmaps/Makefile.am: -------------------------------------------------------------------------------- 1 | pixmapsdir = $(datadir)/pixmaps 2 | pixmaps_DATA = ktsuss.png 3 | EXTRA_DIST = $(pixmaps_DATA) 4 | -------------------------------------------------------------------------------- /pixmaps/ktsuss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nomius/ktsuss/9ea2e839b259f90b509285af49f8dc11851488cb/pixmaps/ktsuss.png -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = ktsuss 2 | 3 | ktsuss_SOURCES = ktsuss.c su_backend.c sudo_backend.c 4 | ktsuss_LDADD = $(DEPS_LIBS) -lutil 5 | AM_CPPFLAGS = $(DEPS_CFLAGS) -DPIXMAPS=\""$(datadir)/pixmaps"\" 6 | -------------------------------------------------------------------------------- /src/errors.h: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 : */ 2 | 3 | /* Copyright (c) 2007-2008, David B. Cortarello 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice 10 | * and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice 12 | * and the following disclaimer in the documentation and/or other materials 13 | * provided with the distribution. 14 | * * Neither the name of Kwort nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include "config.h" 32 | 33 | enum { 34 | ERR_SUCCESS, 35 | ERR_WRONG_USER_OR_PASSWD, 36 | ERR_COMMAND_NOT_FOUND, 37 | ERR_PERMISSION_DENIED, 38 | ERR_MISSING_COMMAND, 39 | ERR_MISSING_USER_AND_COMMAND, 40 | ERR_MISSING_MESSAGE_AND_COMMAND, 41 | ERR_CALLING_SU, 42 | ERR_INVALID_COMMAND 43 | }; 44 | 45 | static const char *KTS_ERRORS[] = { 46 | "Success", 47 | "Invalid username or password", 48 | "Command not found", 49 | "Permission denied", 50 | "No command given", 51 | "No user and command specified", 52 | "No message and command specified", 53 | "Unknown error calling the su command", 54 | "Command passed is invalid" 55 | }; 56 | -------------------------------------------------------------------------------- /src/ktsuss.c: -------------------------------------------------------------------------------- 1 | 2 | /* vim: set sw=4 sts=4 : */ 3 | 4 | /* 5 | * Copyright (c) 2007-2011, David B. Cortarello 6 | * Copyright (c) 2007-2011, Christian Dywan 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice 12 | * and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright notice 14 | * and the following disclaimer in the documentation and/or other materials 15 | * provided with the distribution. 16 | * * Neither the name of Kwort nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #if defined(__FreeBSD__) 43 | #include 44 | #include 45 | #else 46 | #include 47 | #include 48 | #endif 49 | 50 | #include 51 | #include 52 | #include 53 | 54 | #include "config.h" 55 | #include "errors.h" 56 | 57 | #ifdef SUDOPATH 58 | #include "sudo_backend.h" 59 | #endif 60 | 61 | #ifdef SUPATH 62 | #include "su_backend.h" 63 | #endif 64 | 65 | static struct termios orig_termios; 66 | 67 | /* Print's the help text to the terminal and exits with error */ 68 | void say_help(char *str) 69 | { 70 | printf("Usage: %s [OPTION] \n", str); 71 | printf("Run a command as another user\n\n"); 72 | printf("OPTIONS:\n"); 73 | printf("\t-v, --version Gives ktsuss version info\n"); 74 | printf("\t-u, --user USER Runs the command as the given user\n"); 75 | printf("\t-m, --message MESG Change default message in ktsuss window\n"); 76 | printf("\t-h, --help Show this help\n"); 77 | exit(1); 78 | } 79 | 80 | 81 | /* Print's the about text to the terminal and exits with no error */ 82 | void say_about(void) 83 | { 84 | printf("%s - Copyright (c) 2007-2014 David B. Cortarello\n\n", PACKAGE_STRING); 85 | printf("Please report comments, suggestions and bugs to:\n\t%s\n\n", PACKAGE_BUGREPORT); 86 | printf("Check for new versions at:\n\thttps://github.com/nomius/ktsuss\n\n"); 87 | exit(0); 88 | } 89 | 90 | 91 | /* Creates a dialog with the given text error */ 92 | void Werror(int type, char *err_msg, int exit_true, int ret) 93 | { 94 | GtkWidget *dialog_error; 95 | if (!err_msg) 96 | dialog_error = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not run command"); 97 | else 98 | dialog_error = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, err_msg); 99 | 100 | gtk_window_set_title(GTK_WINDOW(dialog_error), "ktsuss"); 101 | gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog_error), KTS_ERRORS[type]); 102 | gtk_dialog_run(GTK_DIALOG(dialog_error)); 103 | gtk_widget_destroy(dialog_error); 104 | 105 | /* In case exit is needed, let's just exit */ 106 | if (exit_true) 107 | exit(ret); 108 | } 109 | 110 | 111 | /* Gets the real full path for the given command */ 112 | char *get_real_name(const char *command) 113 | { 114 | char *real_name = NULL; 115 | char *path = strdup(getenv("PATH")); 116 | GString *new_path = g_string_new(getenv("PATH")); 117 | 118 | /* temporary set PATH to include the sbin directories */ 119 | new_path = g_string_append(new_path, "/usr/sbin:/usr/local/sbin:/sbin"); 120 | setenv("PATH", new_path->str, 1); 121 | 122 | real_name = g_find_program_in_path(command); 123 | 124 | /* Restore the PATH */ 125 | setenv("PATH", path, 1); 126 | 127 | /* Clean up */ 128 | free(path); 129 | g_string_free(new_path, TRUE); 130 | 131 | return real_name; 132 | } 133 | 134 | 135 | /* Set the terminal in raw mode (ttyfd must be a valid terminal file descriptor) */ 136 | void tty_raw(int ttyfd) 137 | { 138 | struct termios raw; 139 | 140 | memcpy(&raw, &orig_termios, sizeof(struct termios)); 141 | raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); 142 | raw.c_oflag &= ~(OPOST); 143 | raw.c_cflag |= (CS8); 144 | raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); 145 | raw.c_cc[VMIN] = 5; raw.c_cc[VTIME] = 8; 146 | raw.c_cc[VMIN] = 0; raw.c_cc[VTIME] = 0; 147 | raw.c_cc[VMIN] = 2; raw.c_cc[VTIME] = 0; 148 | raw.c_cc[VMIN] = 0; raw.c_cc[VTIME] = 8; 149 | if (tcsetattr(ttyfd, TCSAFLUSH, &raw) < 0) 150 | err(1, "tcsetattr()"); 151 | } 152 | 153 | 154 | int main(int argc, char *argv[]) 155 | { 156 | gboolean explicit_username = FALSE; 157 | gboolean explicit_message = FALSE; 158 | int error = 0; 159 | int m = 0, i = 1; 160 | guint counter = 0; 161 | gchar *command = NULL; 162 | gchar *command_run = NULL; 163 | gchar *username = NULL; 164 | gchar *password = NULL; 165 | 166 | uid_t whoami; 167 | struct passwd *pw; 168 | 169 | char err_msg[256]; 170 | 171 | gchar *message = NULL; 172 | 173 | char **cmd_argv = NULL; 174 | GError *cmd_error = NULL; 175 | 176 | GtkWidget *dialog; 177 | GtkSizeGroup *sizegroup; 178 | GtkWidget *hbox; 179 | GtkWidget *image; 180 | GtkWidget *align; 181 | GtkWidget *label; 182 | GtkWidget *user; 183 | GtkWidget *pass; 184 | 185 | gtk_init(&argc, &argv); 186 | 187 | /* Parse arguments */ 188 | while (i < argc) { 189 | if (argv[i][0] != '-') 190 | break; 191 | if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) 192 | say_help(argv[0]); 193 | if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-v")) 194 | say_about(); 195 | if (!strcmp(argv[i], "--user") || !strcmp(argv[i], "-u")) { 196 | if ((username = argv[i + 1]) == NULL) 197 | Werror(ERR_MISSING_USER_AND_COMMAND, NULL, 1, 1); 198 | explicit_username = TRUE; 199 | i += 1; 200 | } 201 | if (!strcmp(argv[i], "--message") || !strcmp(argv[i], "-m")) { 202 | if ((message = argv[i + 1]) == NULL) 203 | Werror(ERR_MISSING_MESSAGE_AND_COMMAND, NULL, 1, 1); 204 | explicit_message = TRUE; 205 | i += 1; 206 | } 207 | i += 1; 208 | } 209 | 210 | if (argv[i] == NULL) 211 | Werror(ERR_MISSING_COMMAND, NULL, 1, 1); 212 | 213 | /* handle arguments and spaces in the subcommand correctly */ 214 | if (! g_shell_parse_argv(argv[i], NULL, &cmd_argv, &cmd_error)) 215 | /* Something bad has happened */ 216 | Werror(ERR_INVALID_COMMAND, cmd_error->message, 1, 1); 217 | 218 | /* Get the full path command */ 219 | command = get_real_name(cmd_argv[0]); 220 | if (command == NULL) 221 | Werror(ERR_INVALID_COMMAND, cmd_argv[0], 1, 1); 222 | 223 | /* Sanity check */ 224 | whoami = getuid(); 225 | if ((pw = getpwuid(whoami)) == NULL) 226 | exit(2 + 0 * fprintf(stderr, "Who you think you are? Houdini?\n")); 227 | 228 | if (!explicit_username) 229 | username = g_strdup("root"); 230 | 231 | if (username && !strcmp(pw->pw_name, username)) { 232 | /* username was me so let's just run it and get the hell out */ 233 | if (execvp(command, &(cmd_argv[0])) == -1) { 234 | Werror(ERR_PERMISSION_DENIED, NULL, 1, 1); 235 | exit(1); 236 | } 237 | /* We should never get here, but just in case */ 238 | exit(0); 239 | } 240 | 241 | if (explicit_username && !explicit_message) 242 | message = g_strdup_printf("Please enter the\npassword for %s:", username); 243 | else if (!explicit_message) 244 | message = g_strdup("Please enter the desired\nusername and password:"); 245 | 246 | dialog = gtk_dialog_new_with_buttons(command, NULL, GTK_DIALOG_NO_SEPARATOR, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); 247 | gtk_window_set_title(GTK_WINDOW(dialog), cmd_argv[0]); 248 | gtk_window_set_icon_name(GTK_WINDOW(dialog), "ktsuss"); 249 | gtk_container_set_border_width(GTK_CONTAINER(dialog), 5); 250 | gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 5); 251 | gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), 5); 252 | hbox = gtk_hbox_new(FALSE, 6); 253 | #if GTK_CHECK_VERSION(2, 10, 0) 254 | image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG); 255 | #else 256 | image = gtk_image_new_from_icon_name("ktsuss", GTK_ICON_SIZE_DIALOG); 257 | #endif 258 | gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); 259 | label = gtk_label_new(message); 260 | gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); 261 | gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); 262 | sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); 263 | if (!explicit_username) { 264 | hbox = gtk_hbox_new(FALSE, 6); 265 | label = gtk_label_new("Username"); 266 | align = gtk_alignment_new(0, 0.5, 0, 0); 267 | gtk_container_add(GTK_CONTAINER(align), label); 268 | gtk_size_group_add_widget(sizegroup, align); 269 | gtk_box_pack_start(GTK_BOX(hbox), align, FALSE, FALSE, 0); 270 | user = gtk_entry_new(); 271 | gtk_entry_set_text(GTK_ENTRY(user), username ? username : "root"); 272 | gtk_box_pack_start(GTK_BOX(hbox), user, FALSE, FALSE, 0); 273 | gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); 274 | } 275 | hbox = gtk_hbox_new(FALSE, 6); 276 | label = gtk_label_new("Password"); 277 | align = gtk_alignment_new(0, 0.5, 0, 0); 278 | gtk_container_add(GTK_CONTAINER(align), label); 279 | gtk_size_group_add_widget(sizegroup, align); 280 | gtk_box_pack_start(GTK_BOX(hbox), align, FALSE, FALSE, 0); 281 | pass = gtk_entry_new_with_max_length(32); 282 | gtk_entry_set_visibility(GTK_ENTRY(pass), FALSE); 283 | gtk_box_pack_start(GTK_BOX(hbox), pass, FALSE, FALSE, 0); 284 | gtk_entry_set_activates_default(GTK_ENTRY(pass), TRUE); 285 | gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); 286 | gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); 287 | gtk_widget_grab_focus(pass); 288 | gtk_widget_show_all(GTK_DIALOG(dialog)->vbox); 289 | 290 | /* Show the dialog up to 3 times */ 291 | while (counter < 3) { 292 | if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) { 293 | if (!explicit_username) 294 | username = strdup(gtk_entry_get_text(GTK_ENTRY(user))); 295 | password = strdup(gtk_entry_get_text(GTK_ENTRY(pass))); 296 | 297 | #ifdef SUDOPATH 298 | if ((error = check_password_sudo(username, password)) == ERR_SUCCESS) { 299 | #else 300 | if ((error = check_password_su(username, password)) == ERR_SUCCESS) { 301 | #endif 302 | gtk_widget_destroy(dialog); 303 | while (gtk_events_pending()) 304 | gtk_main_iteration(); 305 | dialog = NULL; 306 | /* using argv instead of cmd_argv is fine, because 'su' is going 307 | * to implement its only parsing nevertheless */ 308 | command_run = g_strjoinv(" ", &argv[i]); 309 | #ifdef SUDOPATH 310 | run_sudo(username, password, command_run); 311 | #else 312 | run_su(username, password, command_run); 313 | #endif 314 | g_free(command_run); 315 | 316 | counter = 3; 317 | } 318 | if (!explicit_username) { 319 | free(username); 320 | username = NULL; 321 | } 322 | memset(password, '\0', strlen(password)); 323 | free(password); 324 | if (error != ERR_SUCCESS) { 325 | snprintf(err_msg, sizeof(err_msg), "Could not run '%s'", command); 326 | Werror(error, err_msg, 0, 0); 327 | counter++; 328 | } 329 | } 330 | else 331 | break; 332 | if (counter < 3) 333 | gtk_widget_grab_focus(pass); 334 | } 335 | 336 | /* Clean up process */ 337 | if (dialog) 338 | gtk_widget_destroy(dialog); 339 | if ((explicit_username && !explicit_message) || !explicit_message) 340 | free(message); 341 | if (!explicit_username && username) 342 | g_free(username); 343 | 344 | g_strfreev(cmd_argv); 345 | if (cmd_error) 346 | g_error_free(cmd_error); 347 | 348 | return 0; 349 | } 350 | 351 | -------------------------------------------------------------------------------- /src/su_backend.c: -------------------------------------------------------------------------------- 1 | 2 | /* vim: set sw=4 sts=4 : */ 3 | 4 | /* 5 | * Copyright (c) 2007-2011, David B. Cortarello 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice 11 | * and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright notice 13 | * and the following disclaimer in the documentation and/or other materials 14 | * provided with the distribution. 15 | * * Neither the name of Kwort nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "config.h" 33 | #ifdef SUPATH 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #if defined(__FreeBSD__) 45 | #include 46 | #include 47 | #include 48 | #else 49 | #include 50 | #include 51 | #endif 52 | #include 53 | 54 | #include "errors.h" 55 | 56 | #ifndef MAX 57 | #define MAX(a,b) ((a)>(b)?(a):(b)) 58 | #endif 59 | 60 | #define BUFF_SIZE 1024 61 | 62 | static struct termios orig_termios; 63 | 64 | /* Finalize the su call */ 65 | static void end_su(int fd) 66 | { 67 | char buf[BUFF_SIZE]; 68 | fd_set rfds; 69 | struct timeval tv; 70 | 71 | /* If it just ended, let's check if there something in the buffers, blame coreutils su for this ugly hack */ 72 | tv.tv_sec = 0; 73 | tv.tv_usec = 100; 74 | FD_ZERO(&rfds); 75 | FD_SET(fd, &rfds); 76 | if (select(fd+1, &rfds, NULL, NULL, &tv) < 0) 77 | err(1, "select()"); 78 | if (FD_ISSET(fd, &rfds)) 79 | read(fd, buf, BUFF_SIZE); 80 | } 81 | 82 | 83 | /* Finalize the su call */ 84 | static int init_su(int *fdpty, const char *username, const char *password, char *cmd[]) 85 | { 86 | int status = 1, i = 0; 87 | char buf[BUFF_SIZE]; 88 | pid_t pid; 89 | fd_set rfds; 90 | struct timeval tv; 91 | 92 | /* Creates a new terminal */ 93 | if ((pid = forkpty(fdpty, NULL, NULL, NULL)) < 0) err(1, "forkpty()"); 94 | else if (pid == 0) { 95 | setsid(); 96 | signal(SIGHUP, SIG_IGN); 97 | execv(cmd[0], cmd); 98 | err(1, "execv()"); 99 | exit(1); 100 | } 101 | 102 | /* Read the "Password:" prompt */ 103 | for (i = 500; i && status; i--) { 104 | tv.tv_sec = 0; 105 | tv.tv_usec = 10; 106 | FD_ZERO(&rfds); 107 | FD_SET(*fdpty, &rfds); 108 | if (select(*fdpty + 1, &rfds, NULL, NULL, &tv) < 0) 109 | err(1, "select()"); 110 | if (FD_ISSET(*fdpty, &rfds)) { 111 | read(*fdpty, buf, BUFF_SIZE - 1); 112 | status = 0; 113 | } 114 | usleep(1000); 115 | } 116 | 117 | /* Check if we got a limit time */ 118 | if (status) { 119 | kill(pid, SIGKILL); 120 | err(1, "No prompt given by the su command"); 121 | } 122 | 123 | /* Send the password */ 124 | snprintf(buf, 64, "%s\n", password); 125 | write(*fdpty, buf, strlen(buf)); 126 | 127 | /* Read what's left in the buffers */ 128 | end_su(*fdpty); 129 | 130 | return pid; 131 | } 132 | 133 | 134 | /* Check user and password */ 135 | int check_password_su(const char *username, const char *password) 136 | { 137 | int fdpty = 0, status = 0, pid = 0; 138 | #if defined(__FreeBSD__) 139 | char *cmd[6] = { SUPATH, (char *)username, "-m", "-c", "exit", NULL }; 140 | #else 141 | char *cmd[6] = { SUPATH, (char *)username, "-p", "-c", "exit", NULL }; 142 | #endif 143 | 144 | pid = init_su(&fdpty, username, password, cmd); 145 | 146 | waitpid(pid, &status, 0); 147 | 148 | end_su(fdpty); 149 | close(fdpty); 150 | 151 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 152 | return ERR_SUCCESS; 153 | else 154 | if (WIFSIGNALED(status)) { 155 | fprintf(stderr, "Why I was signaled?: %d\n", WTERMSIG(status)); 156 | return -1; 157 | } 158 | return ERR_WRONG_USER_OR_PASSWD; 159 | } 160 | 161 | 162 | /* Run the given command as the given user */ 163 | void run_su(char *username, char *password, char *command) 164 | { 165 | #if defined(__FreeBSD__) 166 | char buf[BUFF_SIZE], *cmd[6] = { SUPATH, username, "-m", "-c", command, NULL }; 167 | #else 168 | char buf[BUFF_SIZE], *cmd[6] = { SUPATH, username, "-p", "-c", command, NULL }; 169 | #endif 170 | int fdpty = 0, status = 0, tty = 1; 171 | pid_t pid = 0; 172 | fd_set rfds; 173 | struct timeval tv; 174 | 175 | pid = init_su(&fdpty, username, password, cmd); 176 | 177 | /* Put the terminal in raw mode */ 178 | if (tcgetattr(STDIN_FILENO, &orig_termios) < 0) { 179 | if (errno == ENOTTY) 180 | errno = tty = 0; 181 | else 182 | err(1, "tcgetattr()"); 183 | } 184 | 185 | if (tty) 186 | tty_raw(STDIN_FILENO); 187 | 188 | while (1) { 189 | waitpid(pid, &status, WNOHANG); 190 | 191 | /* Ok, the program needs some interaction, so this will do it fine */ 192 | tv.tv_sec = 0; 193 | tv.tv_usec = 10; 194 | FD_ZERO(&rfds); 195 | FD_SET(fdpty, &rfds); 196 | FD_SET(STDIN_FILENO, &rfds); 197 | 198 | if (select(MAX(fdpty, STDIN_FILENO)+1, &rfds, NULL, NULL, &tv) < 0) err(1, "select()"); 199 | 200 | if (FD_ISSET(fdpty, &rfds)) { 201 | if ((status = read(fdpty, buf, BUFF_SIZE)) > 0) 202 | write(STDOUT_FILENO, buf, status); 203 | else 204 | break; 205 | 206 | } 207 | else if (FD_ISSET(STDIN_FILENO, &rfds)) { 208 | status = read(STDIN_FILENO, buf, BUFF_SIZE); 209 | write(fdpty, buf, status); 210 | } 211 | usleep(100); 212 | } 213 | 214 | end_su(fdpty); 215 | close(fdpty); 216 | 217 | if (tty) 218 | if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) < 0) 219 | err(1, "tcsetattr()"); 220 | } 221 | 222 | #endif 223 | -------------------------------------------------------------------------------- /src/su_backend.h: -------------------------------------------------------------------------------- 1 | 2 | /* vim: set sw=4 sts=4 tw=80 */ 3 | 4 | /* 5 | * Copyright (c) 2011 , David B. Cortarello 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. All advertising materials mentioning features or use of this software 16 | * must display the following acknowledgement: 17 | * This product includes software developed by David B. Cortarello. 18 | * 4. Neither the name of David B. Cortarello nor the 19 | * names of its contributors may be used to endorse or promote products 20 | * derived from this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY DAVID B. CORTARELLO 'AS IS' AND ANY 23 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL DAVID B. CORTARELLO BE LIABLE FOR ANY 26 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef SU_BACKEND_H 35 | #define SU_BACKEND_H 36 | 37 | int check_password_su(const char *username, const char *password); 38 | void run_su(char *username, char *password, char *command); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/sudo_backend.c: -------------------------------------------------------------------------------- 1 | 2 | /* vim: set sw=4 sts=4 : */ 3 | 4 | /* 5 | * Copyright (c) 2007-2011, David B. Cortarello 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice 11 | * and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright notice 13 | * and the following disclaimer in the documentation and/or other materials 14 | * provided with the distribution. 15 | * * Neither the name of Kwort nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "config.h" 33 | #ifdef SUDOPATH 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #if defined(__FreeBSD__) 45 | #include 46 | #include 47 | #else 48 | #include 49 | #include 50 | #endif 51 | 52 | #include 53 | #include 54 | 55 | #include "errors.h" 56 | 57 | #ifndef MAX 58 | #define MAX(a,b) ((a)>(b)?(a):(b)) 59 | #endif 60 | 61 | #define BUFF_SIZE 1024 62 | 63 | static struct termios orig_termios; 64 | 65 | /* Check user and password */ 66 | int check_password_sudo(const char *username, const char *password) 67 | { 68 | int status = 0, pid = 0, pip[2]; 69 | char *cmd[10] = { SUDOPATH, "-u", (char *)username, "-k", "-S", "-p", "", "-E", "true", NULL }; 70 | char pass[64]; 71 | 72 | if (pipe(pip)) err(1, "pipe()"); 73 | 74 | if ((pid = fork()) < 0) err(1, "fork()"); 75 | else if (pid == 0) { 76 | close(pip[1]); 77 | status = open("/dev/null", O_WRONLY); 78 | dup2(status, STDERR_FILENO); 79 | close(status); 80 | dup2(pip[0], STDIN_FILENO); 81 | execv(cmd[0], cmd); 82 | close(pip[0]); 83 | err(1, "execv()"); 84 | } 85 | close(pip[0]); 86 | sprintf(pass, "%s\n", password); 87 | write(pip[1], pass, strlen(pass)); 88 | close(pip[1]); 89 | 90 | waitpid(pid, &status, 0); 91 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 92 | return ERR_SUCCESS; 93 | else 94 | if (WIFSIGNALED(status)) { 95 | fprintf(stderr, "Why I was signaled?: %d\n", WTERMSIG(status)); 96 | return -1; 97 | } 98 | return ERR_WRONG_USER_OR_PASSWD; 99 | } 100 | 101 | 102 | /* Run the given command as the given user */ 103 | void run_sudo(char *username, char *password, char *command) 104 | { 105 | char buf[BUFF_SIZE], *cmd[10] = { SUDOPATH, "-u", (char *)username, "-k", "-S", "-p", "", "-E", command, NULL }; 106 | int fdpty = 0, status = 0, tty = 1, i = 0; 107 | int pip[2]; 108 | pid_t pid; 109 | fd_set rfds; 110 | struct timeval tv; 111 | 112 | char pass[64]; 113 | 114 | if (pipe(pip)) err(1, "pipe()"); 115 | 116 | /* Creates a new terminal */ 117 | if ((pid = forkpty(&fdpty, NULL, NULL, NULL)) < 0) err(1, "forkpty()"); 118 | else if (pid == 0) { 119 | setsid(); 120 | 121 | close(pip[1]); 122 | dup2(pip[0], STDIN_FILENO); 123 | execv(cmd[0], cmd); 124 | close(pip[0]); 125 | 126 | err(1, "execv()"); 127 | exit(1); 128 | } 129 | 130 | close(pip[0]); 131 | sprintf(pass, "%s\n", password); 132 | write(pip[1], pass, strlen(pass)); 133 | close(pip[1]); 134 | 135 | /* Put the terminal in raw mode */ 136 | if (tcgetattr(STDIN_FILENO, &orig_termios) < 0) { 137 | if (errno == ENOTTY) 138 | errno = tty = 0; 139 | else 140 | err(1, "tcgetattr()"); 141 | } 142 | if (tty) 143 | tty_raw(STDIN_FILENO); 144 | 145 | /*read(fdpty, buf, BUFF_SIZE);*/ 146 | while (!waitpid(pid, &status, WNOHANG)) { 147 | 148 | /* Ok, the program needs some interaction, so this will do it fine */ 149 | tv.tv_sec = 0; 150 | tv.tv_usec = 10; 151 | FD_ZERO(&rfds); 152 | FD_SET(fdpty, &rfds); 153 | FD_SET(STDIN_FILENO, &rfds); 154 | 155 | if (select(MAX(fdpty, STDIN_FILENO)+1, &rfds, NULL, NULL, &tv) < 0) err(1, "select()"); 156 | 157 | if (FD_ISSET(fdpty, &rfds)) { 158 | status = read(fdpty, buf, BUFF_SIZE); 159 | write(STDOUT_FILENO, buf, status); 160 | } 161 | else if (FD_ISSET(STDIN_FILENO, &rfds)) { 162 | status = read(STDIN_FILENO, buf, BUFF_SIZE); 163 | write(fdpty, buf, status); 164 | } 165 | usleep(100); 166 | } 167 | 168 | close(fdpty); 169 | 170 | if (tty) 171 | if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) < 0) 172 | err(1, "tcsetattr()"); 173 | } 174 | 175 | #endif 176 | -------------------------------------------------------------------------------- /src/sudo_backend.h: -------------------------------------------------------------------------------- 1 | 2 | /* vim: set sw=4 sts=4 tw=80 */ 3 | 4 | /* 5 | * Copyright (c) 2011 , David B. Cortarello 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. All advertising materials mentioning features or use of this software 16 | * must display the following acknowledgement: 17 | * This product includes software developed by David B. Cortarello. 18 | * 4. Neither the name of David B. Cortarello nor the 19 | * names of its contributors may be used to endorse or promote products 20 | * derived from this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY DAVID B. CORTARELLO 'AS IS' AND ANY 23 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL DAVID B. CORTARELLO BE LIABLE FOR ANY 26 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef SUDO_BACKEND_H 35 | 36 | int check_password_sudo(const char *username, const char *password); 37 | void run_sudo(char *username, char *password, char *command); 38 | 39 | #define SUDO_BACKEND_H 40 | 41 | #endif 42 | --------------------------------------------------------------------------------