// // File: // // simple cgi program so can use a web server as a front end // to vserver, some people behind firewalls can only talk to // a web server. // // Written by: David M. Stanhope // #include #include #include #include #include #include #include #include #include #include "timestamp.h" static char server_name[] = "127.0.0.1"; static int server_port = 8009 ; FILE *fp_debug = NULL; #define LOG(x...) if(fp_debug) { fprintf(fp_debug, ## x); fflush(fp_debug); } #define MSG2(x) // nothing #define ERR(x) LOG x #define SOCKET int #define Socket_Error() Show_Error() static char * Show_Error(void) { static char buf[256]; sprintf(buf, "%d:%s", errno, strerror(errno)); return buf; } #include "util.c" void respond(char *msg) { write(fileno(stdout), msg, strlen(msg) + 1); } // TODO: COULD MOVE THIS TO VSERVER SINCE MIGHT BE BETTER PLACE char * decode_escapes(char *src, char *dst) { int c, t, esc_flag = 0; while(c = *src++) { if(esc_flag == 0) { if(c == '\\') { esc_flag = 1; } else { *dst++ = c; } } else if(esc_flag == 1) { if((c >= '0') && (c <= '9')) { t = (c - '0'); } else if((c >= 'A') && (c <= 'F')) { t = ((c - 'A') + 10); } else if((c >= 'a') && (c <= 'f')) { t = ((c - 'a') + 10); } else { return NULL; // return error } esc_flag = 2; } else if(esc_flag == 2) { if((c >= '0') && (c <= '9')) { *dst++ = ((t << 4) | (c - '0')); } else if((c >= 'A') && (c <= 'F')) { *dst++ = ((t << 4) | ((c - 'A') + 10)); } else if((c >= 'a') && (c <= 'f')) { *dst++ = ((t << 4) | ((c - 'a') + 10)); } else { return NULL; // return error } esc_flag = 0; } else // bogus state, should never happen { return NULL; // return error } } if(esc_flag) // unfinished escape sequence { return NULL; // return error } *dst = '\0'; // insure valid termination return dst; } main(int argc, char *argv[]) { int fd, n, r, err = 0; char *p, *query_string, *peer_ip, *peer_port; char buf[4096]; struct sockaddr_in server; if((query_string = getenv("QUERY_STRING")) == NULL) { err++; } if((peer_ip = getenv("REMOTE_ADDR" )) == NULL) { err++; } if((peer_port = getenv("REMOTE_PORT" )) == NULL) { err++; } fp_debug = fopen("/tmp/vs_cgi.log", "a"); LOG("-----------------------------------------------------------\n") LOG("Connection at (%s)\n", timestamp()) if(query_string) { LOG("QUERY_STRING(%s)\n" , query_string) } if(peer_ip ) { LOG("REMOTE_ADDRESS(%s)\n", peer_ip ) } if(peer_port ) { LOG("REMOTE_PORT(%s)\n" , peer_port ) } if(err) { LOG("Missing required info\n") exit(-1); } // client will have escaped the spaces in 'query' so un-escape them if((p = decode_escapes(query_string, buf)) == NULL) { LOG("BOGUS QUERY_STRING\n") exit(-1); } else { // add REMOTE_ADDRESS and REMOTE_PORT to message since 'vserver' // can't see client via getpeername() sprintf(p, "|peer_ip=%s|peer_port=%s", peer_ip, peer_port); // LOG("QUERY(%s)\n", buf) } // connect to 'vserver' if((fd = Connect_TCP(server_name, server_port)) < 0) { // error message already output exit(-1); } n = strlen(buf) + 1; // lenght + '\0' if((r = write(fd, buf, n)) != n) // send message to 'vserver' { LOG("Write To Server Failed, sent(%d), returned(%d)\n", n, r) close(fd); exit(-1); } // TODO: READ UNTIL TIMEOUT OR GET TRAILING '\0' n = read(fd, buf, sizeof(buf)); // get response from 'vserver' // TODO: ADD SOME VALIDATION close(fd); if(n < 0) { LOG("Response Error(%s)\n", Show_Error()) exit(-1); } else if(n == 0) { LOG("Response Empty\n") exit(-1); } else if(buf[n - 1] != '\0') { LOG("Response Bogus, No EOS\n") exit(-1); } else { LOG("Response(%s)\n", buf); } // -------------------------------------------------- // spit out minimum header to keep web-server happy // -------------------------------------------------- fprintf(stdout, "Content-Type: text/html\n"); fprintf(stdout, "\n"); fflush(stdout); respond(buf); exit(0); } // // The End! //