cmdproxyd-0.1/000075500000000000000000000000001060653120400133565ustar00rootroot00000000000000cmdproxyd-0.1/.gitignore000064400000000000000000000000211060653120400153370ustar00rootroot00000000000000cmdproxyd *.[do] cmdproxyd-0.1/Makefile000064400000000000000000000031541060653120400150210ustar00rootroot00000000000000# # Copyright (C) 2004 Dmitry V. Levin # # Makefile for the cmdproxyd project. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # PROJECT = cmdproxyd TARGETS = $(PROJECT) sbindir = /usr/sbin DESTDIR = MKDIR_P = mkdir -p INSTALL = install CFLAGS = -pipe -Wall -Werror -W -O2 SRC = cmdproxyd.c OBJ = $(SRC:.c=.o) DEP = $(SRC:.c=.d) .PHONY: all install clean indent all: $(TARGETS) $(PROJECT): $(OBJ) $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@ install: all $(MKDIR_P) -m755 $(DESTDIR)$(sbindir) $(INSTALL) -p -m755 cmdproxyd $(DESTDIR)$(sbindir)/ clean: $(RM) $(TARGETS) $(DEP) $(OBJ) core *~ indent: indent *.c # We need dependencies only if goal isn't "indent" or "clean". ifneq ($(MAKECMDGOALS),indent) ifneq ($(MAKECMDGOALS),clean) %.d: %.c @echo Making dependences for $< @$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed -e 's|\($*\)\.o[ :]*|\1.o $@ : |g' > $@; [ -s $@ ] || $(RM) $@" ifneq ($(DEP),) -include $(DEP) endif endif # clean endif # indent cmdproxyd-0.1/cmdproxyd.c000064400000000000000000000123221060653120400155330ustar00rootroot00000000000000 /* Copyright (C) 2004 Dmitry V. Levin The command proxy daemon. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void sigchld_handler ( __attribute__ ((unused)) int signo) { while (waitpid (-1, 0, WNOHANG) > 0) ; } static void __attribute__ ((__noreturn__)) usage (int rc) { extern const char *__progname; fprintf ((rc == EXIT_SUCCESS) ? stdout : stderr, "Usage: %s bind_address.. runas program...\n", __progname); exit (rc); } static int bind_address (const char *address) { struct sockaddr_un sun; if (strlen (address) >= sizeof (sun)) error (EXIT_FAILURE, EINVAL, "cannot bind socket `%s'", address); memset (&sun, 0, sizeof (sun)); sun.sun_family = AF_UNIX; strcpy (sun.sun_path, address); int fd = socket (PF_UNIX, SOCK_STREAM, 0); if (fd < 0) error (EXIT_FAILURE, errno, "cannot create socket `%s'", address); if (bind (fd, (struct sockaddr *) &sun, sizeof (sun))) { unlink (address); if (bind (fd, (struct sockaddr *) &sun, sizeof (sun))) error (EXIT_FAILURE, errno, "cannot bind socket `%s'", address); } if (chmod (address, 0666)) error (EXIT_FAILURE, errno, "cannot set permissions of socket `%s'", address); if (listen (fd, 5) < 0) error (EXIT_FAILURE, errno, "listen"); int flags; if ((flags = fcntl (fd, F_GETFL, 0)) == -1) error (EXIT_FAILURE, errno, "fcntl: F_GETFL"); flags |= O_NONBLOCK; if (fcntl (fd, F_SETFL, flags) == -1) error (EXIT_FAILURE, errno, "fcntl: F_SETFL"); if ((flags = fcntl (fd, F_GETFD, 0)) == -1) error (EXIT_FAILURE, errno, "fcntl: F_GETFD"); flags |= FD_CLOEXEC; if (fcntl (fd, F_SETFD, flags) == -1) error (EXIT_FAILURE, errno, "fcntl: F_SETFD"); return fd; } static void handle_socket (int fd, const char *address, const char *const *args) { struct sockaddr_un sun; memset (&sun, 0, sizeof (sun)); sun.sun_family = AF_UNIX; socklen_t sunlen = sizeof (sun); int accfd = accept (fd, (struct sockaddr *) &sun, &sunlen); if (accfd < 0) { if (errno != EINTR) { syslog (LOG_ERR, "accept: %s[%d]: %m", address, fd); sleep (1); } return; } struct ucred sucred; socklen_t credlen = sizeof (struct ucred); if (getsockopt (accfd, SOL_SOCKET, SO_PEERCRED, &sucred, &credlen)) { close (accfd); syslog (LOG_ERR, "getsockopt: SO_PEERCRED: %s[%d]: %m", address, fd); sleep (1); return; } pid_t pid = fork (); if (pid < 0) { close (accfd); syslog (LOG_ERR, "fork: %m"); sleep (1); return; } if (pid) { close (accfd); return; } dup2 (accfd, 0); close (accfd); syslog (LOG_INFO, "request from %s, uid=%u, executing %s", address, sucred.uid, args[0]); execvp (args[0], (char *const *) args); syslog (LOG_ERR, "execvp: %s: %m", args[0]); exit (EXIT_FAILURE); } int main (int ac, const char *av[]) { signal (SIGCHLD, sigchld_handler); if (ac < 3) usage (EXIT_FAILURE); const char *runas = 0; const char *const *args = 0; int nsockets = 0; int i; for (i = 1; i < ac; ++i) { if (runas) { args = &av[i]; break; } if (av[i][0] == '/') { ++nsockets; continue; } if (!nsockets) usage (EXIT_FAILURE); runas = av[i]; } if (!nsockets || !runas || !args) usage (EXIT_FAILURE); struct passwd *pw = getpwnam (runas); if (!pw) error (EXIT_FAILURE, 0, "user `%s' lookup failed", runas); int sockfd[nsockets]; for (i = 1; i <= nsockets; ++i) sockfd[i - 1] = bind_address (av[i]); if (initgroups (runas, pw->pw_gid)) error (EXIT_FAILURE, errno, "initgroups"); if (setgid (pw->pw_gid)) error (EXIT_FAILURE, errno, "setgid"); if (setuid (pw->pw_uid)) error (EXIT_FAILURE, errno, "setuid"); endpwent (); if (daemon (0, 0)) error (EXIT_FAILURE, errno, "daemon"); openlog ("cmdproxyd", LOG_PERROR | LOG_PID, LOG_MAIL); for (;;) { int i, maxfd = 0; fd_set r; FD_ZERO (&r); for (i = 0; i < nsockets; ++i) { FD_SET (sockfd[i], &r); if (sockfd[i] > maxfd) maxfd = sockfd[i]; } int rc = select (1 + sockfd[nsockets - 1], &r, 0, 0, 0); if (rc < 0) { if (errno == EINTR) continue; syslog (LOG_ERR, "select: %m"); sleep (1); continue; } for (i = 0; i < nsockets; ++i) if (FD_ISSET (sockfd[i], &r)) handle_socket (sockfd[i], av[1 + i], args); } } cmdproxyd-0.1/cmdproxyd.init000075500000000000000000000021021060653120400162520ustar00rootroot00000000000000#!/bin/sh # # chkconfig: - 95 05 # description: \ # The command proxy daemon. # # processname: cmdproxyd WITHOUT_RC_COMPAT=1 # Source function library. . /etc/init.d/functions LOCKFILE=/var/lock/subsys/cmdproxyd RUN_AS=cmdproxyd BIND_ADDR= RUN_CMD= RETVAL=0 # Source config. SourceIfNotEmpty /etc/sysconfig/cmdproxyd start() { [ -n "$RUN_AS" -a -n "$BIND_ADDR" -a -n "$RUN_CMD" ] || return 0 start_daemon --lockfile "$LOCKFILE" --expect-user "$RUN_AS" -- cmdproxyd $BIND_ADDR "$RUN_AS" $RUN_CMD RETVAL=$? return $RETVAL } stop() { stop_daemon --lockfile "$LOCKFILE" --expect-user "$RUN_AS" cmdproxyd RETVAL=$? return $RETVAL } restart() { stop start } # See how we were called. case "$1" in start) start ;; stop) stop ;; reload|restart) restart ;; condstop) if [ -e "$LOCKFILE" ]; then stop fi ;; condrestart|condreload) if [ -e "$LOCKFILE" ]; then restart fi ;; status) status --expect-user "$RUN_AS" cmdproxyd RETVAL=$? ;; *) msg_usage "${0##*/} {start|stop|restart|condstop|condrestart|status}" RETVAL=1 esac exit $RETVAL cmdproxyd-0.1/cmdproxyd.spec000064400000000000000000000016771060653120400162560ustar00rootroot00000000000000Name: cmdproxyd Version: 0.1 Release: alt2 Summary: A command proxy daemon License: GPL Group: System/Servers Packager: Dmitry V. Levin Source: %name-%version.tar PreReq: shadow-utils, service %description This is a command proxy daemon. %prep %setup -q %build %make_build CFLAGS="%optflags -Werror -W" %install %make_install install DESTDIR=%buildroot install -pD -m755 %name.init %buildroot%_initdir/%name install -pD -m644 %name.sysconfig %buildroot%_sysconfdir/sysconfig/%name %post /usr/sbin/groupadd -r -f %name /usr/sbin/useradd -r -g %name -d /dev/null -s /dev/null -n %name >/dev/null 2>&1 ||: %post_service %name %preun %preun_service %name %files %config %_initdir/* %config(noreplace) %_sysconfdir/sysconfig/%name %_sbindir/* %changelog * Tue Apr 10 2007 Dmitry V. Levin 0.1-alt2 - Reduced macro abuse in specfile. * Wed May 26 2004 Dmitry V. Levin 0.1-alt1 - Initial revision. cmdproxyd-0.1/cmdproxyd.sysconfig000064400000000000000000000002401060653120400173110ustar00rootroot00000000000000# Username to use for executed commands. RUN_AS=cmdproxyd # List of unix domain sockets to bind. BIND_ADDR= # Command with its arguments to execute. RUN_CMD=