Yet Another Intercepting Proxy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

162 lines
3.8 KiB

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "database.h"
#include "proxy.h"
#include "config.h"
#include "request.h"
#include "response.h"
#include "ssl.h"
#define PACKAGE_NAME "WICTP"
#define DEFAULT_DATABASE "data.sqlite"
#define DEFAULT_CONFIG "config.json"
#define DEFAULT_PORT 8080
unsigned int validatePortNumber(unsigned int portNumber){
// Given that we are dealing with unsined ints, we don't need to worry about
// checking for values less than 0
if ( portNumber > 65535 ){
printf( "Port %i is invalid, using default of %i", portNumber, DEFAULT_PORT );
return DEFAULT_PORT;
}
return portNumber;
}
void printHelp(){
printf("Usage: %s [options]\n", PACKAGE_NAME);
printf( "Options are:\n" );
printf( "\t --config OPTION VALUE Sets config option OPTION to VALUE\n" );
printf( "\t --print-config Prints current config\n" );
}
int startListener(unsigned int port){
//we need to act as an http server
int server_fd;
struct sockaddr_in address;
memset( &address, 0, sizeof(address) );
int addrlen = sizeof(address);
Response *response;
char *responseStr;
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
return -1;
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( port );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) != 0) {
perror("bind failed");
return -1;
}
if (listen(server_fd, 3) != 0) {
perror("listen");
return -1;
}
return server_fd;
}
int main(int argc, char**argv){
Config *config = configDefaults();
int listener;
for ( unsigned int i = 1; i < argc; i++ ){
if ( strcmp( argv[i], "--config" ) == 0 ){
if ( i + 2 < argc ){
setConfig( config, argv[i + 1], argv[i + 2] );
i += 2;
} else {
printf("--config requires 2 positional arguments\n");
}
} else if ( strcmp( argv[i], "--print-config" ) == 0 ){
printConfig(config);
return 0;
} else if ( strcmp( argv[i], "--help" ) == 0 ){
printHelp();
return 0;
} else {
printf("Unknown option %s\n", argv[i]);
}
}
if (path_exists( config->userConfig ) ){
printf("User config file exists but still needs to be parsed\n");
}
if (path_exists( config->localConfig ) ){
printf("Local config file exists but still needs to be parsed\n");
}
if ( !db_file_exists(config->database) ){
printf("Creating DB");
db_create(config->database);
}
maybeMakeDir( getConfigDir() );
if (!path_exists( config->keyfile ) ){
printf("Creating keyfile\n");
if ( !create_and_save_key(config->keyfile) ){
return 1;
}
}
if (!path_exists( config->certfile ) ){
printf("Creating cert\n");
if ( !create_and_save_cert(config->certfile, read_private_key( config->keyfile) ) ){
return 1;
}
}
listener = startListener(config->port);
if ( listener < 0 ){
return 1;
}
while ( true ){
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
int client = 0;
Request *request = NULL;
printf("Listening on port %i\n", config->port);
if ((client = accept(listener, (struct sockaddr *)&addr,
&addrlen))<0) {
perror("accept");
return 0;
}
//I think eventually I'd like a different thread here for each request
//Not sure how to do that yet though so I'll keep everything on the main
//thread
request = newRequestFromSocket(client);
if ( strcmp( request->host, "" ) == 0 ){
// If the host is not defined, then it is not a proxy request
// Note that the host here is where the request should be sent, not
// necesarily the hosts header
webserverRequest(request, client);
} else {
proxyRequest(request, client);
}
close(client);
freeRequest( request );
}
return 0;
}