pkgsrc/security/py-prewikka/files/runPrewikka.c

146 lines
3.1 KiB
C

#define PREWIKKA_HTTPD_USER "@PREWIKKA_USER@"
#define PREWIKKA_HTTPD_PATH "@PREFIX@/bin/prewikka-httpd"
#define PYTHON "@PYTHONBIN@"
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <pwd.h>
#include <syslog.h>
#define MAX_ARGS 40
#ifndef TRUE
#define TRUE 1
#endif /* TRUE */
#ifndef FALSE
#define FALSE 0
#endif /* FALSE */
void error_sys(char *str)
{
/* Output error message to syslog */
char msg[1024];
snprintf(msg, sizeof(msg), "run-prewikka-httpd : %s : %s", str, strerror(errno));
syslog(LOG_ALERT, msg);
}
int obtainUIDandGID(const char *name, uid_t *pw_uid, gid_t *pw_gid)
{
/* Obtain UID and GID from passwd entry identified by name */
struct passwd *pw_entry;
char msg[100];
if ((pw_entry = getpwnam(name)) == NULL)
{
snprintf(msg, sizeof(msg), "failed to get password entry for %s", name);
error_sys(msg);
return FALSE;
}
else
{
*pw_uid = pw_entry->pw_uid;
*pw_gid = pw_entry->pw_gid;
return TRUE;
}
}
int main (int argc, char **argv )
{
pid_t pid;
uid_t UID;
gid_t GID;
pid_t pidwait;
int waitstat;
/* Sanity check */
if (argc > MAX_ARGS)
{
error_sys("arg buffer too small");
exit(-1);
}
/* fork child that will become prewikka-httpd */
if ((pid = fork()) < 0)
error_sys("fork error");
else
{
if (pid == 0)
{
/* We're the child */
char *args[MAX_ARGS];
unsigned int i;
/* Become session leader */
setsid();
/* Clear out file creation mask */
umask(0);
if (!obtainUIDandGID(PREWIKKA_HTTPD_USER, &UID, &GID))
exit(-1);
/* Drop privileges immediately */
if (setgid(GID) < 0)
{
/* It is VERY important to check return
value and not continue if setgid fails
*/
error_sys ("setgid failed");
exit (-1);
}
if (setuid(UID) < 0)
{
/* It is VERY important to check return
value and not continue if setuid fails
*/
error_sys ("setuid failed");
exit (-1);
}
/* Build calling argv */
args[0] = PYTHON;
args[1] = PREWIKKA_HTTPD_PATH;
for (i=1;i<argc;i++)
{
args[i+1] = argv[i];
args[i+2] = NULL;
}
/* Finally transform self into prewikka-httpd */
if (execvp(PYTHON, args) < 0)
error_sys("execve error");
else
; /* avoid if-then ambiguity */
}
else
{
/* We're the parent
Terminate
*/
exit(0);
}
}
}