/* * querysh -- handle a CGI query of type GET or POST, place results * in environment variables, and call shell script. * * (c) 1995, Gilles Detillieux, Physiology, University of Manitoba. * * - this program is to be used as a shell substitute for CGI shell * scripts that handle forms queries. The shell script should * begin with the lines: * * #!/your/path/to/command/querysh * #?/path/to/real/sh * * This program will be called with the arguments to the script. * It handles CGI GET or POST queries, and places the fields in * environment variables, with "QSH_" prepended to the field names. * (Only field names composed of alphanumerics or '_' are allowed.) * It also places in the environment a variable called "QSH_Fields", * which contains a list of the variables it read from the form. * It then calls the real shell to interpret the script. * If the second line is omitted, it defaults to /bin/sh. * * Compile and install this program somewhere suitable * (for example, /usr/local/etc/httpd/querysh might be a good place). * Make sure you set the first line in your CGI shell scripts to * point to this location. Note that on some systems, the first line * must not be longer than 32 characters (the size of an a.out header), * so the path to querysh should be shorter than that, or the program * won't run. * * As tempting as it may be, DO NOT install this program right in the * cgi-bin directory; since it runs any shell script it's given, * this would be very unsafe. */ #include #include /* * The following 4 functions were taken from NCSA httpd's cgi-src/util.c, * so thanks to Rob McCool & the gang and NCSA. This one's for you... * * Portions developed at the National Center for Supercomputing * Applications at the University of Illinois at Urbana-Champaign. * * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, * FOR THE SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT * LIMITATION, WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A * PARTICULAR PURPOSE. */ char x2c(char *what) { register char digit; digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0')); digit *= 16; digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0')); return(digit); } void unescape_url(char *url) { register int x,y; for (x=0,y=0;url[y];++x,++y) { if ((url[x] = url[y]) == '%') { url[x] = x2c(&url[y+1]); y+=2; } } url[x] = '\0'; } void plustospace(char *str) { register int x; for (x=0;str[x];x++) if (str[x] == '+') str[x] = ' '; } int ind(char *s, char c) { register int x; for (x=0;s[x];x++) if (s[x] == c) return x; return -1; } /* * OK, from here on, I assume full responsability... */ char html_hdr[] = "Content-type: text/html\n\n"; char query_err[] = "\n\ Query Form Error\n\

Query Form Error

\n"; char html_end[] = "\n\n"; char query_fields[] = "QSH_Fields="; char query_prefix[] = "QSH_"; char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"; main(int argc, char *argv[]) { register int x, y; int cl; char *query = NULL; char *fields, *var, *arg; char **args; char line[256]; FILE *fp; var = getenv("REQUEST_METHOD"); if (var != NULL && strcmp(var, "GET") == 0) { var = getenv("QUERY_STRING"); if (var != NULL && (cl = strlen(var)) > 0) { if ((query = (char *) malloc(sizeof(char) * (cl + 1))) == NULL) goto memerr; strcpy(query, var); } else if (var != NULL && var[0] == '\0') query = var; /* allow empty GET queries */ } else if (var != NULL && strcmp(var, "POST") == 0) { var = getenv("CONTENT_TYPE"); if (var != NULL && strcmp(var, "application/x-www-form-urlencoded") != 0) { printf(html_hdr); printf(query_err); printf("This script can only be used to decode form results.\n"); printf(html_end); exit(1); } var = getenv("CONTENT_LENGTH"); if (var != NULL && (cl = atoi(var)) > 0) { if ((query = (char *) malloc(sizeof(char) * (cl + 1))) == NULL) goto memerr; cl = fread(query, sizeof(char), cl, stdin); if (cl <= 0) query = NULL; else query[cl] = '\0'; } } else { printf(html_hdr); printf(query_err); printf( "This script should be referenced with a METHOD of POST or GET.\n"); printf("If you don't understand this, see this\n"); printf("forms overview.\n"); printf(html_end); exit(1); } if (query == NULL) { printf(html_hdr); printf(query_err); printf("No query information to decode.\n"); printf(html_end); exit(1); } if ((fields = (char *) malloc(sizeof(query_fields))) == NULL) goto memerr; strcpy(fields, query_fields); while (query[0]) { var = query; if ((x = ind(query, '&')) < 0) query += strlen(query); else { query += x; *query++ = '\0'; } if (var[0]) { plustospace(var); unescape_url(var); if ((x = ind(var, '=')) < 0) continue; /* ignore non-variable */ for (y = 0; y < x; ++y) if (ind(alphanum, var[y]) < 0) break; if (y < x) continue; /* ignore invalid variable name */ if ((arg = (char *) malloc(sizeof(char) * (strlen(query_prefix) + strlen(var) + 1))) == NULL) goto memerr; strcpy(arg, query_prefix); strcat(arg, var); if (putenv(arg) < 0) goto memerr; x = ind(arg, '='); y = strlen(fields); if ((fields = (char *) realloc(fields, sizeof(char) * (y+x+1))) == NULL) goto memerr; if (fields[y-1] != '=') fields[y++] = ' '; strncpy(&fields[y], arg, x); fields[y+x] = '\0'; } } if (putenv(fields) < 0) goto memerr; if (argc < 2 || (fp = fopen(argv[1], "r")) == NULL) { printf(html_hdr); printf(query_err); printf("Can't open command script: %s\n", argc < 2 ? "not given" : argv[1]); printf(html_end); exit(1); } var = "/bin/sh"; arg = NULL; if (fgets(line, sizeof(line), fp) != NULL && fgets(line, sizeof(line), fp) != NULL && line[0] == '#' && line[1] == '?') { y = 2; while (line[y] == ' ' || line[y] == '\t') ++y; if (line[y]) var = &line[y]; while (line[y] != ' ' && line[y] != '\t' && line[y] != '\n' && line[y]) ++y; if (line[y] == ' ' || line[y] == '\t') { line[y++] = '\0'; while (line[y] == ' ' || line[y] == '\t') ++y; if (line[y]) arg = &line[y]; while (line[y] != ' ' && line[y] != '\t' && line[y] != '\n' && line[y]) ++y; } line[y] = '\0'; } fclose(fp); args = argv; if (arg != NULL) { /* make room for new argument */ if ((args = (char **) malloc(sizeof(char **) * (argc + 2))) == NULL) goto memerr; args[0] = argv[0]; args[1] = arg; for (x = 1; x <= argc; ++x) args[x+1] = argv[x]; } execv(var, args); printf(html_hdr); printf(query_err); printf("Can't execute shell %s for command script %s\n", var, argv[1]); printf(html_end); exit(1); memerr: printf(html_hdr); printf(query_err); printf("Not enough memory available to process this form.\n"); printf(html_end); exit(1); }