Use pam
This commit is contained in:
parent
306bb5fcfc
commit
7bc3242654
5
Makefile
5
Makefile
@ -25,11 +25,14 @@ DIET+=-Os
|
||||
endif
|
||||
endif
|
||||
|
||||
CC:=$(DIET) $(CC)
|
||||
# CC:=$(DIET) $(CC)
|
||||
|
||||
.PHONY: all install clean
|
||||
all: execwrap
|
||||
|
||||
execwrap: execwrap.o
|
||||
$(CC) -o $@ $< -lpam
|
||||
|
||||
install: execwrap
|
||||
install -d $(DESTDIR)/usr/sbin/ $(DESTDIR)/usr/share/man/man8/
|
||||
install -s -m 755 execwrap $(DESTDIR)/usr/sbin/
|
||||
|
2
README
2
README
@ -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:
|
||||
|
||||
> 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
|
||||
it work, preferably C99. To install, make sure the file is owned by the super user and has
|
||||
|
2
debian/control
vendored
2
debian/control
vendored
@ -2,7 +2,7 @@ Source: execwrap
|
||||
Section: net
|
||||
Priority: extra
|
||||
Maintainer: Stefan Bühler <stbuehler@web.de>
|
||||
Build-Depends: cdbs, debhelper (>= 5)
|
||||
Build-Depends: cdbs, debhelper (>= 5), libpam-dev
|
||||
Standards-Version: 3.8.0
|
||||
Homepage: http://cyanite.org/projects/execwrap/
|
||||
Vcs-Git: git://cyanite.org/execwrap
|
||||
|
92
execwrap.c
92
execwrap.c
@ -1,4 +1,4 @@
|
||||
/*
|
||||
// /*
|
||||
|
||||
Superuser-exec wrapper for HTTP serves and other needs (made especially for lighttpd).
|
||||
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_CHILD_ABNORMAL_EXIT 25
|
||||
#define RC_MISSING_PWENT 26
|
||||
|
||||
#define RC_PAM_FAILED 27
|
||||
|
||||
/* User configuration. */
|
||||
#include "execwrap_config.h"
|
||||
@ -127,6 +127,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <sys/types.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_misc.h>
|
||||
|
||||
#if USE_SYSLOG
|
||||
|
||||
# include <syslog.h>
|
||||
@ -147,6 +151,83 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#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. */
|
||||
int pid;
|
||||
void (*oldHandler)(int);
|
||||
@ -296,6 +377,10 @@ int main(int argc, char* argv[], char* envp[])
|
||||
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). */
|
||||
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. */
|
||||
int status;
|
||||
wait(&status);
|
||||
|
||||
close_pam_session();
|
||||
|
||||
if(WIFEXITED(status)) return WEXITSTATUS(status);
|
||||
return RC_CHILD_ABNORMAL_EXIT;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user