X-Git-Url: https://git.distorted.org.uk/~mdw/userv-utils/blobdiff_plain/a8e8db26410497a781ca36f59951201d55711f3a..0324503152d6edb67572b45225745441913ae55e:/www-cgi/ucgitarget.c diff --git a/www-cgi/ucgitarget.c b/www-cgi/ucgitarget.c index 9780e36..a24867d 100644 --- a/www-cgi/ucgitarget.c +++ b/www-cgi/ucgitarget.c @@ -3,11 +3,15 @@ * environment variables are USERV_U_E_... */ /* - * Copyright (C) 1998-1999,2003 Ian Jackson + * Copyright 1996-2013 Ian Jackson + * Copyright 1998 David Damerell + * Copyright 1999,2003 + * Chancellor Masters and Scholars of the University of Cambridge + * Copyright 2010 Tony Finch * * This 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but @@ -16,15 +20,13 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with userv-utils; if not, write to the Free Software - * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Id$ + * along with userv-utils; if not, see http://www.gnu.org/licenses/. */ #include #include #include +#include #include #include #include @@ -32,7 +34,7 @@ #include "ucgi.h" -static const char *const envok[]= { +static const char *const default_envok[]= { "AUTH_TYPE", "CONTENT_LENGTH", "CONTENT_TYPE", @@ -59,6 +61,11 @@ static const char *const envok[]= { "PATH_INFO", "PATH_TRANSLATED", "QUERY_STRING", + "REDIRECT_HANDLER", + "REDIRECT_SCRIPT_URI", + "REDIRECT_SCRIPT_URL", + "REDIRECT_STATUS", + "REDIRECT_URL", "REMOTE_ADDR", "REMOTE_HOST", "REMOTE_USER", @@ -76,6 +83,10 @@ static const char *const envok[]= { "SERVER_PROTOCOL", "SERVER_SIGNATURE", "SERVER_SOFTWARE", + "SSL_CIPHER", + "SSL_CLIENT_S_DN", + "SSL_CLIENT_VERIFY", + "SSL_PROTOCOL", 0 }; @@ -85,33 +96,53 @@ static void setenvar(const char *fulln, unsetenv(fulln); } -int main(int argc, const char **argv) { +int main(int argc, char **argv) { char *scriptpath, *newvar; const char *nextslash, *lastslash, *pathi, *ev, *ev2, *scriptdir, *av; + const char *const *envok; const char **arguments; size_t scriptdirlen, scriptpathlen, l; struct stat stab; - int r, nargs; + int i, r, nargs; + const char *filters= 0; ev= getenv("USERV_U_DEBUG"); if (ev && *ev) debugmode= 1; D( if (debugmode) printf(";;; UCGITARGET\n"); ) - if (argc > MAX_ARGS) error("too many arguments"); + if (argc > MAX_ARGS) error("too many arguments", 500); + + for (;;) { + i= getopt(argc, argv, "+e:"); if (i < 0) break; + switch (i) { + case 'e': filters= optarg; break; + default: error("bad command line", 500); break; + } + } + argc -= optind; argv += optind; - if (!*++argv) error("no script directory argument"); - ev= getenv("HOME"); if (!ev) error("no HOME env. var"); + if (!*argv) error("no script directory argument", 500); + ev= getenv("HOME"); if (!ev) error("no HOME env. var", 500); l= strlen(*argv)+strlen(ev); newvar= xmalloc(l+2); sprintf(newvar,"%s/%s",ev,*argv); scriptdir= newvar; scriptdirlen= strlen(scriptdir); - filter_environment(0, "USERV_U_E_", envok, setenvar, 0); + if (filters) + envok= load_filters(LOADF_MUST, filters, LF_END); + else { + envok= load_filters(0, + ".userv/ucgitarget.env-filter", + "/etc/userv/ucgitarget.env-filter", + LF_END); + } + + filter_environment(0, "USERV_U_E_", envok, default_envok, setenvar, 0); scriptpath= 0; pathi= getenv("PATH_INFO"); - if (!pathi) error("PATH_INFO not found"); + if (!pathi) error("PATH_INFO not found", 500); lastslash= pathi; D( if (debugmode) { printf(";; find script name...\n" @@ -119,23 +150,25 @@ int main(int argc, const char **argv) { pathi); } ) for (;;) { - if (*lastslash != '/') error("PATH_INFO expected slash not found"); - if (lastslash[1]=='.' || lastslash[1]=='#' || !lastslash[1]) error("bad char begin"); + if (*lastslash != '/') error("PATH_INFO expected slash not found", 400); + if (lastslash[1]=='.' || lastslash[1]=='#' || !lastslash[1]) + error("bad char begin", 400); nextslash= strchr(lastslash+1,'/'); if (!nextslash) nextslash= lastslash+1+strlen(lastslash+1); - if (!nextslash) error("insufficient elements in PATH_INFO"); - if (nextslash==lastslash+1) error("empty component in PATH_INFO"); - if (nextslash-pathi > MAX_SCRIPTPATH_LEN) error("PATH_INFO script path too long"); + if (!nextslash) error("insufficient elements in PATH_INFO", 400); + if (nextslash==lastslash+1) error("empty component in PATH_INFO", 400); + if (nextslash-pathi > MAX_SCRIPTPATH_LEN) + error("PATH_INFO script path too long", 400); scriptpathlen= scriptdirlen+(nextslash-pathi); scriptpath= xrealloc(scriptpath,scriptpathlen+1); strcpy(scriptpath,scriptdir); memcpy(scriptpath+scriptdirlen,pathi,nextslash-pathi); scriptpath[scriptpathlen]= 0; - if (scriptpath[scriptpathlen-1]=='~') error("bad char end"); + if (scriptpath[scriptpathlen-1]=='~') error("bad char end", 400); D( if (debugmode) printf(";; try `%s'\n", scriptpath); ) r= stat(scriptpath,&stab); if (r) syserror("stat script"); if (S_ISREG(stab.st_mode)) break; - if (!S_ISDIR(stab.st_mode)) error("script not directory or file"); + if (!S_ISDIR(stab.st_mode)) error("script not directory or file", 500); lastslash= nextslash; } D( if (debugmode) printf(";; found script: tail = `%s'\n", nextslash); ) @@ -150,7 +183,7 @@ int main(int argc, const char **argv) { ev= getenv("SCRIPT_NAME"); if (ev) { - ev2= getenv("USER"); if (!ev2) error("no USER variable"); + ev2= getenv("USER"); if (!ev2) error("no USER variable", 500); newvar= xmalloc(strlen(ev)+2+strlen(ev2)+scriptpathlen-scriptdirlen+2); sprintf(newvar,"%s/~%s%s",ev,ev2,scriptpath+scriptdirlen); xsetenv("SCRIPT_NAME",newvar,1);