From fdf6c19932ae3de217a11b64365815561101e29f Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 22 Mar 2016 00:27:42 +0000 Subject: [PATCH] cgi-fcgi-perl: wip, computes socket path --- cprogs/Makefile | 4 +- cprogs/cgi-fcgi-perl.c | 135 ++++++++++++++++++++++++++++++++++++++++- cprogs/common.c | 6 ++ cprogs/common.h | 3 + 4 files changed, 146 insertions(+), 2 deletions(-) diff --git a/cprogs/Makefile b/cprogs/Makefile index c07dbdc..7bb1e27 100644 --- a/cprogs/Makefile +++ b/cprogs/Makefile @@ -58,7 +58,6 @@ writebuffer: writebuffer.o wrbufcore.o rwbuffer.o trivsoundd: trivsoundd.o wrbufcore.o rwbuffer.o really: really.o myopt.o acctdump: acctdump.o myopt.o -cgi-fcgi-perl: cgi-fcgi-perl.o myopt.o acctdump.o really.o myopt.o rcopy-repeatedly.o: myopt.h readbuffer.o writebuffer.o rwbuffer.o wrbufcore.o trivsoundd.o: rwbuffer.h @@ -77,6 +76,9 @@ rcopy-repeatedly: LDLIBS += -lm -lrt watershed: watershed.o common.o watershed: LDLIBS += -lnettle -lgmp +cgi-fcgi-perl: cgi-fcgi-perl.o myopt.o common.o +cgi-fcgi-perl: LDLIBS += -lnettle -lgmp + watershed.txt: watershed.c sed '/^$$/,$$d' <$^ >$@.new && mv -f $@.new $@ diff --git a/cprogs/cgi-fcgi-perl.c b/cprogs/cgi-fcgi-perl.c index 037bd86..617f8f0 100644 --- a/cprogs/cgi-fcgi-perl.c +++ b/cprogs/cgi-fcgi-perl.c @@ -37,6 +37,9 @@ * used. The substring is chosen so that the whole path is 10 bytes * shorter than sizeof(sun_path). But always at least 33 characters. * + * is truncated at the first `.' and after the first 32 + * characters. + * * Algorithm: * - see if /var/run/user exists * if so, lstat /var/run/user/ and check that @@ -55,17 +58,35 @@ * - run cgi-fcgi -connect SOCKET SCRIPT */ +#include "common.h" + #include #include #include #include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include #include "myopt.h" +#define die common_die +#define diee common_diee + +#define MINHEXHASH 33 + static const char *ident; static int numservers; -static void diee(const char *m) { +void diee(const char *m) { fprintf(stderr,"cgi-fcgi-: error: %s failed: %s\n", m, strerror(errno)); exit(127); } @@ -89,7 +110,119 @@ static const struct cmdinfo cmdinfos[]= { { 0 } }; +static uid_t us; +static const char *run_base, *command, *socket_path; + +static bool find_run_base_var_run(void) { + struct stat stab; + char *try; + int r; + + try = m_asprintf("%s/%lu", "/var/run/user", us); + r = lstat(try, &stab); + if (r<0) { + if (errno == ENOENT || + errno == ENOTDIR || + errno == EACCES || + errno == EPERM) + return 0; /* oh well */ + diee("stat /var/run/user/UID"); + } + if (!S_ISDIR(stab.st_mode)) { + fprintf(stderr,"%s not a directory, falling back to ~\n", try); + return 0; + } + if (stab.st_uid != us) { + fprintf(stderr,"%s not owned by uid %lu, falling back to ~\n", + try, (unsigned long)us); + return 0; + } + if (stab.st_mode & 0077) { + fprintf(stderr,"%s writeable by group or other, falling back to ~\n",try); + return 0; + } + run_base = m_asprintf("%s/%s", try, "cgi-fcgi-perl"); + return 1; +} + +static bool find_run_base_home(void) { + struct passwd *pw; + struct utsname ut; + char *dot, *try; + int r; + + pw = getpwuid(us); if (!pw) diee("getpwent(uid)"); + + r = uname(&ut); if (r) diee("uname(2)"); + dot = strchr(ut.nodename, '.'); + if (dot) *dot = 0; + if (sizeof(ut.nodename) > 32) + ut.nodename[32] = 0; + + try = m_asprintf("%s/%s/%s", pw->pw_dir, ".cgi-fcgi-perl", ut.nodename); + run_base = try; + return 1; +} + +static void find_socket_path(void) { + struct sockaddr_un sun; + + us = getuid(); if (us==(uid_t)-1) diee("getuid"); + + find_run_base_var_run() || + find_run_base_home() || + (abort(),0); + + int maxidentlen = sizeof(sun.sun_path) - strlen(run_base) - 10 - 2; + + if (!ident) { + if (maxidentlen < MINHEXHASH) { + fprintf(stderr,"cgi-fcgi-perl: base directory `%s'" + " leaves only %d characters for command name hash" + " which is too little (<%d)\n", + run_base, maxidentlen, MINHEXHASH); + exit(127); + } + + int identlen = maxidentlen > 64 ? 64 : maxidentlen; + char *hexident = xmalloc(identlen + 2); + struct sha256_ctx sc; + unsigned char bbuf[32]; + int i; + + sha256_init(&sc); + sha256_update(&sc,strlen(command)+1,command); + sha256_digest(&sc,sizeof(bbuf),bbuf); + + for (i=0; i maxidentlen) { + fprintf(stderr,"cgi-fgci-perl: base directory `%s'" + " plus ident `%s' too long (with spare) for socket\n", + run_base, ident); + exit(127); + } + + socket_path = m_asprintf("%s/g%s",run_base,ident); +} + int main(int argc, const char *const *argv) { myopt(&argv, cmdinfos); + + command = *argv++; + if (!command || *argv) { + fprintf(stderr,"wrong number of arguments\n"); + exit(127); + } + + find_socket_path(); + + printf(">%s<\n",socket_path); + exit(0); } diff --git a/cprogs/common.c b/cprogs/common.c index 26dc476..b054292 100644 --- a/cprogs/common.c +++ b/cprogs/common.c @@ -35,3 +35,9 @@ char *m_asprintf(const char *fmt, ...) { va_start(al,fmt); s= m_vasprintf(fmt,al); va_end(al); return s; } + +void *xmalloc(size_t sz) { + void *r= malloc(sz); + if (!r) common_diee("malloc"); + return r; +} diff --git a/cprogs/common.h b/cprogs/common.h index ca0609b..a7a2cdd 100644 --- a/cprogs/common.h +++ b/cprogs/common.h @@ -30,6 +30,7 @@ #include #include +#include char *m_vasprintf(const char *fmt, va_list al); char *m_asprintf(const char *fmt, ...); @@ -38,4 +39,6 @@ char *m_asprintf(const char *fmt, ...); void common_die(const char *what); void common_diee(const char *what); /* prints errno */ +void *xmalloc(size_t sz); + #endif /*COMMON_H*/ -- 2.30.2