This commit is contained in:
Stefan Bühler 2009-10-23 10:40:30 +02:00
parent 306bb5fcfc
commit 7bc3242654
4 changed files with 96 additions and 5 deletions

View File

@ -25,11 +25,14 @@ DIET+=-Os
endif endif
endif endif
CC:=$(DIET) $(CC) # CC:=$(DIET) $(CC)
.PHONY: all install clean .PHONY: all install clean
all: execwrap all: execwrap
execwrap: execwrap.o
$(CC) -o $@ $< -lpam
install: execwrap install: execwrap
install -d $(DESTDIR)/usr/sbin/ $(DESTDIR)/usr/share/man/man8/ install -d $(DESTDIR)/usr/sbin/ $(DESTDIR)/usr/share/man/man8/
install -s -m 755 execwrap $(DESTDIR)/usr/sbin/ install -s -m 755 execwrap $(DESTDIR)/usr/sbin/

2
README
View File

@ -110,7 +110,7 @@ ENV_DEBUG Controls the name of environment variable used to enable d
There is no Makefile right now, but compile is as simple as: There is no Makefile right now, but compile is as simple as:
> gcc -W -Wall -O2 -o execwrap execwrap.c && strip execwrap > gcc -W -Wall -O2 -o execwrap execwrap.c -lpam && strip execwrap
Or similar, depending on taste. You need something other than an ancient compiler to make Or similar, depending on taste. You need something other than an ancient compiler to make
it work, preferably C99. To install, make sure the file is owned by the super user and has it work, preferably C99. To install, make sure the file is owned by the super user and has

2
debian/control vendored
View File

@ -2,7 +2,7 @@ Source: execwrap
Section: net Section: net
Priority: extra Priority: extra
Maintainer: Stefan Bühler <stbuehler@web.de> Maintainer: Stefan Bühler <stbuehler@web.de>
Build-Depends: cdbs, debhelper (>= 5) Build-Depends: cdbs, debhelper (>= 5), libpam-dev
Standards-Version: 3.8.0 Standards-Version: 3.8.0
Homepage: http://cyanite.org/projects/execwrap/ Homepage: http://cyanite.org/projects/execwrap/
Vcs-Git: git://cyanite.org/execwrap Vcs-Git: git://cyanite.org/execwrap

View File

@ -1,4 +1,4 @@
/* // /*
Superuser-exec wrapper for HTTP serves and other needs (made especially for lighttpd). Superuser-exec wrapper for HTTP serves and other needs (made especially for lighttpd).
Allows programs to be run with configurable uid/gid. Allows programs to be run with configurable uid/gid.
@ -84,7 +84,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define RC_BAD_OPTION 24 #define RC_BAD_OPTION 24
#define RC_CHILD_ABNORMAL_EXIT 25 #define RC_CHILD_ABNORMAL_EXIT 25
#define RC_MISSING_PWENT 26 #define RC_MISSING_PWENT 26
#define RC_PAM_FAILED 27
/* User configuration. */ /* User configuration. */
#include "execwrap_config.h" #include "execwrap_config.h"
@ -127,6 +127,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sys/types.h> #include <sys/types.h>
#include <grp.h> #include <grp.h>
#include <sys/types.h>
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#if USE_SYSLOG #if USE_SYSLOG
# include <syslog.h> # include <syslog.h>
@ -147,6 +151,83 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif /* USE_SYSLOG */ #endif /* USE_SYSLOG */
#define UNUSED(x) ((void)(x))
static int execwrap_conv(int num_msg, const struct pam_message **msg, struct pam_response **response, void *appdata_ptr) {
struct pam_response *pr;
const struct pam_message *pm;
int n;
UNUSED(appdata_ptr);
if ((*response = calloc(num_msg, sizeof(struct pam_response))) == NULL)
return(PAM_CONV_ERR);
for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) {
switch (pm->msg_style) {
case PAM_PROMPT_ECHO_ON:
case PAM_PROMPT_ECHO_OFF:
// No input available!
goto err;
case PAM_TEXT_INFO:
if (pm->msg)
puts(pm->msg);
break;
case PAM_ERROR_MSG:
if (pm->msg) {
fputs(pm->msg, stderr);
fputc('\n', stderr);
}
break;
default:
goto err;
}
}
return PAM_SUCCESS;
err:
free(*response);
*response = NULL;
return(PAM_CONV_ERR);
}
static pam_handle_t *pamh;
// return 0 on success
int setup_pam_session(const char *username) {
static struct pam_conv pam_conv;
int pam_status;
pam_conv.conv = execwrap_conv;
pam_status = pam_start("execwrap", username, &pam_conv, &pamh);
if (pam_status != PAM_SUCCESS) {
puts("unable to initialize PAM");
return 1;
}
(void) pam_set_item(pamh, PAM_USER, username);
(void) pam_set_item(pamh, PAM_RUSER, "www-data");
(void) pam_setcred(pamh, PAM_ESTABLISH_CRED);
if ((pam_status = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
(void) pam_end(pamh, pam_status | PAM_DATA_SILENT);
pamh = NULL;
puts("unable to open PAM session");
return 2;
}
return 0;
}
void close_pam_session() {
(void) pam_close_session(pamh, 0);
if (pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT) != PAM_SUCCESS) {
puts("unable to close PAM session");
}
pamh = NULL;
}
/* The global child PID and previous SIGTERM handler. */ /* The global child PID and previous SIGTERM handler. */
int pid; int pid;
void (*oldHandler)(int); void (*oldHandler)(int);
@ -296,6 +377,10 @@ int main(int argc, char* argv[], char* envp[])
if(oldHandler == SIG_ERR) return RC_SIGNAL_HANDLER; if(oldHandler == SIG_ERR) return RC_SIGNAL_HANDLER;
} }
/* setup pam session for limits */
if (setup_pam_session(pwent->pw_name)) return RC_PAM_FAILED;
if (non_resident) close_pam_session();
/* Fork off (or, if we are a non-resident wrapper, just carry on). */ /* Fork off (or, if we are a non-resident wrapper, just carry on). */
if(non_resident || !(pid = fork())) if(non_resident || !(pid = fork()))
{ {
@ -363,6 +448,9 @@ int main(int argc, char* argv[], char* envp[])
/* Here we're in the parent. Wait for the child to be done, and return. */ /* Here we're in the parent. Wait for the child to be done, and return. */
int status; int status;
wait(&status); wait(&status);
close_pam_session();
if(WIFEXITED(status)) return WEXITSTATUS(status); if(WIFEXITED(status)) return WEXITSTATUS(status);
return RC_CHILD_ABNORMAL_EXIT; return RC_CHILD_ABNORMAL_EXIT;
} }