diff options
author | Aaron Ball <nullspoon@iohq.net> | 2016-04-03 12:35:36 -0600 |
---|---|---|
committer | Aaron Ball <nullspoon@iohq.net> | 2016-04-03 12:39:29 -0600 |
commit | 9c9a3d1d62b1876c8969ce06b1a9abd2264ac4bd (patch) | |
tree | 3c8b6861021995b369a81c04fa6ed5ce586a37ca /src | |
download | remoteinfo-9c9a3d1d62b1876c8969ce06b1a9abd2264ac4bd.tar.gz remoteinfo-9c9a3d1d62b1876c8969ce06b1a9abd2264ac4bd.tar.xz |
Currently parses the query string for the key "q", and outputs
REMOTE_ADDR if q == ip, or HTTP_USER_AGENT if q == agent.
Also includes a lot of error handling in case the user tries to cause a
buffer overflow of qs. Contains a set default of 512 bytes for each
query string key and value.
Also note that this commit contains a lot of useless experimental code
that needs to be cleaned up and/or broken out into files other than
main.c (yick).
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..1bc49e7 --- /dev/null +++ b/src/main.c @@ -0,0 +1,173 @@ +/** + * Copyright (C) 2014 Aaron Ball <nullspoon@iohq.net> + * + * Remoteinfo 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 3 of the License, or + * (at your option) any later version. + * + * Remoteinfo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with remoteinfo. If not, see <http://www.gnu.org/licenses/>. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define qsmax 512 + +/** + * Searches the query string for the specified key, and copies the value + * to the out variable. + * + * @param char* key Key to search the query string for + * @param int len Maximum length of key and value (for security reasons) + * @param char* out Pointer to output variable value will be copied to + * + * @return int Found (1), not found (0), or error (-1) + */ +int getqs(char* key, int len, char* out) { + char* qs; + char* val; + int valstart; + int i; + + // Get the query string + qs = getenv("QUERY_STRING"); + + // Exit early if the query string was not found. + if(qs == NULL) return -1; + + // Search for the key in the query string + val = strstr(qs, key); + + // Exit early if the key/value was not found. + if(val == NULL) return 0; + + i = 0; + // Find the equals sign + while(val[i] != '=') { + // break if we hit a qs delimiter (&) + if(val[i] == '&') return 0; + // Break if we hit the maximum length (for security, to avoid buffer + // overflows or overflow dumps. + if((i + 1) == len) return 0; + i++; + } + // Repoint the start of val + val = &val[i + 1]; + + // Reset i to 0 + i = 0; + while(val[i] != '\0') { + // break if we hit a qs delimiter (&) + if(val[i] == '&') break; + // Break if we hit the maximum length (for security, to avoid buffer + // overflows or overflow dumps. + if((i + 1) == len) break; + // copy char in + out[i] = val[i]; + i++; + } + out[i] = '\0'; + return 1; +} + + +void read_file(char* path, FILE* out) { + FILE *f = fopen(path, "r"); + + fprintf(out, "<pre>"); + + char buf; + while((buf = fgetc(f)) != EOF) { + if(buf == '<') { + // Print an html line break if we fine a newline + fprintf(out, "<"); + } else { + fprintf(out, "%c", buf); + } + } + fprintf(out, "</pre>"); + + fclose(f); +} + +void stylesheet(char* path, FILE* out) { + fprintf(out, "<link rel=\"stylesheet\" "); + fprintf(out, "type=\"text/css\" href=\"%s\" />\n", path); +} + +int print_html_header(FILE* out) { + fprintf(out, "<html>\n"); + fprintf(out, "<head>\n"); + stylesheet("style.css", out); + fprintf(out, "</head>\n"); + fprintf(out, "<body>\n"); +} + +void print_body(FILE* out) { + char q[qsmax]; + int found; + char* reqvar; + + // Get value of q + found = getqs("q", qsmax, q); + if(found != 1) return; + + // All looks well, let's try to handle the query string. + if(strcmp(q, "ip") == 0) { + // IP request + reqvar = getenv("REMOTE_ADDR"); + if(reqvar == NULL) { + fprintf(out, "ERROR: REMOTE_ADDR not set."); + } else { + fprintf(out, "%s", getenv("REMOTE_ADDR")); + } + } else if(strcmp(q, "agent") == 0) { + // Useragent request + reqvar = getenv("HTTP_USER_AGENT"); + if(reqvar == NULL) { + fprintf(out, "ERROR: HTTP_USER_AGENT not set."); + } else { + fprintf(out, "%s", getenv("HTTP_USER_AGENT")); + } + } + fprintf(out, "\n"); +} + + +void print_html_footer(FILE* out) { + fprintf(out, "</body>\n</html>\n"); +} + + +int main(int argc, char* argv[]) { + // Print the content type header (very useful) + fprintf(stdout, "Content-Type: text/html;\n\n"); + + // Check if "type" qs is specified, and handle appropriately if it is + // This is for printing in different formats (eg: style html, json, etc) + int found; + char type[qsmax]; + found = getqs("type", qsmax, type); + + if(found == 1) { + // Prints the html header (<html><head>, etc.) + print_html_header(stdout); + } + + print_body(stdout); + + // Annnnd the footer + if(found == 1) { + // Prints the html footer (</body></html>) + print_html_footer(stdout); + } + + return 0; +} |