repo: rename library and update docs
This commit is contained in:
parent
9002b5688c
commit
1bc58618e5
12
Makefile
12
Makefile
|
@ -1,14 +1,14 @@
|
|||
CC=bear --append -- gcc
|
||||
CFLAGS= -g3 -Wall -Werror
|
||||
|
||||
all: proxy
|
||||
all: proxlib
|
||||
|
||||
proxy: proxy.c
|
||||
$(CC) $(CFLAGS) -o proxy.o -c proxy.c
|
||||
$(CC) $(CFLAGS) -o proxy proxy.o
|
||||
proxy: proxlib.c
|
||||
$(CC) $(CFLAGS) -o proxlib.o -c proxlib.c
|
||||
$(CC) $(CFLAGS) -o proxlib proxlib.o
|
||||
|
||||
clean:
|
||||
rm -f proxy *.o
|
||||
rm -f proxlib *.o
|
||||
|
||||
tar:
|
||||
tar -cvzf proxy.tgz proxy.c structs.h README Makefile
|
||||
tar -cvzf proxlib.tgz proxlib.c proxlib.h README Makefile
|
||||
|
|
20
README
20
README
|
@ -1,8 +1,8 @@
|
|||
+==================+
|
||||
| CUSTOM PROXY |
|
||||
+==================+
|
||||
+=============+
|
||||
| proxlib |
|
||||
+=============+
|
||||
|
||||
Proxy for HTTP/1.0 standard protocol
|
||||
Proxy C library for HTTP/s protocol
|
||||
|
||||
RFC: datatracker.ietf.org/doc/html/rfc1945
|
||||
RES: cs.princeton.edu/courses/archive/spr13/cos461/assignments-proxy.html
|
||||
|
@ -12,8 +12,16 @@
|
|||
|
||||
TECHNICALS
|
||||
|
||||
Parsing is done through a chain of regex expressions that verify
|
||||
the format of received HTTP/1.0 messages.
|
||||
Parsing is carried by a sub-library which I wrote named parslib.
|
||||
|
||||
TODO
|
||||
|
||||
* Connect with parslib
|
||||
* Parse port out of Host header (default_value:80)
|
||||
* Implement server message parsing
|
||||
* Verify and search for memory leaks
|
||||
* More testing, debugging, fixing
|
||||
* Implement HTTPS with OpenSSL
|
||||
|
||||
COMMITS
|
||||
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <regex.h>
|
||||
#include "structs.h"
|
||||
#include "proxlib.h"
|
||||
|
||||
int on = 1;
|
||||
int debug = 1;
|
||||
struct request *clt_data;
|
||||
regex_t preg;
|
||||
|
@ -20,13 +21,17 @@ int statem;
|
|||
int clt_sock = -1;
|
||||
int srv_sock = -1;
|
||||
char *clt_msg = NULL;
|
||||
int clt_msg_len = 0;
|
||||
char *srv_msg = NULL;
|
||||
int clt_msg_len = 0;
|
||||
int srv_msg_len = 0;
|
||||
|
||||
void *extractsub(const char *msg, regmatch_t match) {
|
||||
void *buf = NULL;
|
||||
int buflen = match.rm_eo - match.rm_so;
|
||||
void *buf = (void *) calloc(1, buflen);
|
||||
if (!buflen)
|
||||
goto _return;
|
||||
|
||||
buf = (void *) calloc(1, buflen);
|
||||
if (buf == NULL)
|
||||
goto _return;
|
||||
|
||||
|
@ -77,6 +82,37 @@ _err:
|
|||
return -1;
|
||||
}
|
||||
|
||||
int parse_host(char *buff) {
|
||||
int ret;
|
||||
|
||||
ret = regcomp(&preg, REGEX_HOST, REG_EXTENDED);
|
||||
if (ret != 0)
|
||||
goto _err;
|
||||
|
||||
ret = regexec(&preg, buff, REGEX_MATCHN, pmatch, 0);
|
||||
if (ret != 0)
|
||||
goto _err;
|
||||
|
||||
char *host_name = extractsub(buff, pmatch[1]);
|
||||
if (!host_name)
|
||||
goto _err;
|
||||
|
||||
char *host_port = extractsub(buff, pmatch[2]);
|
||||
if (!host_port) {
|
||||
host_port = PROXY_DEF_PORT;
|
||||
}
|
||||
|
||||
clt_data->host_name = host_name;
|
||||
clt_data->host_port = host_port;
|
||||
|
||||
regfree(&preg);
|
||||
return 0;
|
||||
|
||||
_err:
|
||||
regfree(&preg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int parse_title(char *msgbuff) {
|
||||
int ret;
|
||||
|
||||
|
@ -109,13 +145,18 @@ _err:
|
|||
|
||||
}
|
||||
|
||||
void free_title() {
|
||||
void free_host(void) {
|
||||
free(clt_data->host_name);
|
||||
free(clt_data->host_port);
|
||||
}
|
||||
|
||||
void free_title(void) {
|
||||
free(clt_data->method);
|
||||
free(clt_data->uri);
|
||||
free(clt_data->ver);
|
||||
}
|
||||
|
||||
void free_headers() {
|
||||
void free_headers(void) {
|
||||
for (int i = 0; i < clt_data->header_num; i++) {
|
||||
struct header *header = &clt_data->headers[i];
|
||||
free(header->key);
|
||||
|
@ -124,12 +165,27 @@ void free_headers() {
|
|||
free(clt_data->headers);
|
||||
}
|
||||
|
||||
void free_message() {
|
||||
void free_clt_data(void) {
|
||||
free_host();
|
||||
free_title();
|
||||
free_headers();
|
||||
free(clt_data);
|
||||
}
|
||||
|
||||
void free_srv_data(void) {
|
||||
|
||||
}
|
||||
|
||||
void free_msg_buffs(void) {
|
||||
free(clt_msg);
|
||||
free(srv_msg);
|
||||
}
|
||||
|
||||
void free_data(void) {
|
||||
free_clt_data();
|
||||
free_srv_data();
|
||||
}
|
||||
|
||||
int parse_line(char *line, int line_count) {
|
||||
int ret = 0;
|
||||
|
||||
|
@ -157,19 +213,20 @@ char *getheader(char *key) {
|
|||
|
||||
void do_err(void) {
|
||||
int statem_code = statem & (~STATEM_ERR);
|
||||
fprintf(stderr, "[%d,%d,%d] Errored out!\n", statem, statem_code, STATEM_ERR);
|
||||
fprintf(stderr, "[%d,%d,%d] Errored out!\n", statem, statem_code,
|
||||
STATEM_ERR);
|
||||
}
|
||||
|
||||
int do_fwd_clt(void) {
|
||||
int bytes = 0;
|
||||
int ret = 0;
|
||||
do {
|
||||
ret = send(clt_sock, srv_msg+bytes, srv_msg_len-bytes, 0);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
while (bytes < srv_msg_len) {
|
||||
ret = write(clt_sock, srv_msg+bytes, srv_msg_len-bytes);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
bytes += ret;
|
||||
} while (bytes < srv_msg_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -183,21 +240,21 @@ int do_prs_srv(void) {
|
|||
int do_rcv_srv(void) {
|
||||
int bytes = 0;
|
||||
int ret = 0;
|
||||
do {
|
||||
ret = recv(srv_sock, srv_msg+bytes, PROXY_MAX_MSGLEN-bytes, 0);
|
||||
while (bytes < PROXY_MAX_MSGLEN) {
|
||||
ret = recv(srv_sock, srv_msg+bytes, PROXY_MAX_MSGLEN-bytes, MSG_PEEK);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return -1;
|
||||
if (!ret)
|
||||
break;
|
||||
ret = recv(srv_sock, srv_msg+bytes, PROXY_MAX_MSGLEN-bytes, 0);
|
||||
|
||||
bytes += ret;
|
||||
} while (bytes < sizeof(PROXY_MAX_MSGLEN));
|
||||
bytes += ret;
|
||||
}
|
||||
|
||||
srv_msg_len = bytes;
|
||||
|
||||
if (debug) {
|
||||
fprintf(stdout, "[%d] Received server message: %s\n", statem, srv_msg);
|
||||
}
|
||||
if (debug)
|
||||
fprintf(stdout, "[%d] Received server message of size %d bytes\n", statem, srv_msg_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -207,6 +264,10 @@ int do_con_srv(void) {
|
|||
char *host = getheader("Host");
|
||||
if (!host)
|
||||
return -1;
|
||||
|
||||
ret = parse_host(host);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res;
|
||||
|
@ -215,11 +276,12 @@ int do_con_srv(void) {
|
|||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
ret = getaddrinfo(host, "80", &hints, &res);
|
||||
ret = getaddrinfo(clt_data->host_name, clt_data->host_port, &hints, &res);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
ret = srv_sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
ret = srv_sock = socket(res->ai_family, res->ai_socktype,
|
||||
res->ai_protocol);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -233,13 +295,13 @@ int do_con_srv(void) {
|
|||
int do_fwd_srv(void) {
|
||||
int bytes = 0;
|
||||
int ret = 0;
|
||||
do {
|
||||
ret = send(srv_sock, clt_msg+bytes, clt_msg_len-bytes, 0);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
while (bytes < clt_msg_len) {
|
||||
ret = write(srv_sock, clt_msg+bytes, clt_msg_len-bytes);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
bytes += ret;
|
||||
} while (bytes < clt_msg_len);
|
||||
bytes += ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -268,21 +330,22 @@ int do_prs_clt(void) {
|
|||
int do_rcv_clt(void) {
|
||||
int bytes = 0;
|
||||
int ret = 0;
|
||||
do {
|
||||
ret = recv(clt_sock, clt_msg+bytes, PROXY_MAX_MSGLEN-bytes, 0);
|
||||
while (bytes < PROXY_MAX_MSGLEN) {
|
||||
ret = recv(clt_sock, clt_msg+bytes, PROXY_MAX_MSGLEN-bytes, MSG_PEEK);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
if (!ret)
|
||||
break;
|
||||
|
||||
ret = recv(clt_sock, clt_msg+bytes, PROXY_MAX_MSGLEN-bytes, 0);
|
||||
|
||||
bytes += ret;
|
||||
} while (bytes < sizeof(PROXY_MAX_MSGLEN));
|
||||
}
|
||||
|
||||
clt_msg_len = bytes;
|
||||
|
||||
if (debug) {
|
||||
fprintf(stdout, "[%d] Received client message: %s\n", statem, clt_msg);
|
||||
}
|
||||
if (debug)
|
||||
fprintf(stdout, "[%d] Received client message of size %d bytes\n", statem, clt_msg_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -304,6 +367,8 @@ int do_alloc(void) {
|
|||
}
|
||||
|
||||
void do_clear(void) {
|
||||
statem = STATEM_RCV_CLT;
|
||||
|
||||
memset(clt_msg, 0, PROXY_MAX_MSGLEN);
|
||||
memset(srv_msg, 0, PROXY_MAX_MSGLEN);
|
||||
memset(clt_data, 0, sizeof(struct request));
|
||||
|
@ -312,7 +377,7 @@ void do_clear(void) {
|
|||
srv_msg_len = 0;
|
||||
}
|
||||
|
||||
void dostatem() {
|
||||
void do_statem() {
|
||||
int ret = do_alloc();
|
||||
if (ret < 0) {
|
||||
do_err();
|
||||
|
@ -356,7 +421,6 @@ void dostatem() {
|
|||
}
|
||||
|
||||
if (statem & STATEM_FWD_CLT) {
|
||||
statem = STATEM_RCV_CLT;
|
||||
do_clear();
|
||||
continue;
|
||||
}
|
||||
|
@ -364,9 +428,8 @@ void dostatem() {
|
|||
statem <<= 1;
|
||||
}
|
||||
|
||||
free_message();
|
||||
free(clt_msg);
|
||||
free(srv_msg);
|
||||
free_msg_buffs();
|
||||
free_data();
|
||||
}
|
||||
|
||||
void dohelp() {
|
||||
|
@ -382,38 +445,36 @@ void dohelp() {
|
|||
);
|
||||
}
|
||||
|
||||
int doserver(void) {
|
||||
int ret, server_socket;
|
||||
int do_srv(void) {
|
||||
int ret, proxy_sock;
|
||||
struct sockaddr_in serv_addr;
|
||||
|
||||
ret = server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
ret = proxy_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to create a socket to listen on\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int on = 1;
|
||||
ret = setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
ret = setsockopt(proxy_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed flagging server socket as reusable\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in serv_addr;
|
||||
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
serv_addr.sin_port = htons(PROXY_PORT);
|
||||
|
||||
ret = bind(server_socket, (struct sockaddr *) &serv_addr,
|
||||
ret = bind(proxy_sock, (struct sockaddr *) &serv_addr,
|
||||
sizeof(serv_addr));
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to bind to port %d\n", PROXY_PORT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = listen(server_socket, PROXY_CONN);
|
||||
ret = listen(proxy_sock, PROXY_CONN);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to listen on port %d\n", PROXY_PORT);
|
||||
return -1;
|
||||
|
@ -422,12 +483,12 @@ int doserver(void) {
|
|||
fprintf(stdout, "Listening on port %d\n", PROXY_PORT);
|
||||
|
||||
for (;;) {
|
||||
struct sockaddr_in client_addr;
|
||||
socklen_t client_addrlen = sizeof(client_addr);
|
||||
int client_socket;
|
||||
struct sockaddr_in new_clt_addr;
|
||||
socklen_t new_clt_addr_len= sizeof(new_clt_addr);
|
||||
int new_clt_sock;
|
||||
|
||||
ret = client_socket = accept(server_socket, (struct sockaddr *)
|
||||
&client_addr, &client_addrlen);
|
||||
ret = new_clt_sock = accept(proxy_sock, (struct sockaddr *)
|
||||
&new_clt_addr, &new_clt_addr_len);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to establish socket connection with"
|
||||
"client\n");
|
||||
|
@ -435,29 +496,27 @@ int doserver(void) {
|
|||
}
|
||||
|
||||
ret = fork();
|
||||
switch (ret) {
|
||||
case -1:
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "[CLIENT SOCKET %d] Failed to fork child process"
|
||||
"to handle the request\n", client_socket);
|
||||
"to handle the request\n", new_clt_sock);
|
||||
return -1;
|
||||
break;
|
||||
case 0:
|
||||
clt_sock = client_socket;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
clt_sock = new_clt_sock;
|
||||
statem = STATEM_RCV_CLT;
|
||||
dostatem();
|
||||
do_statem();
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
fprintf(stdout, "[PROGRAM] Successfully forked a new child process"
|
||||
" with PID %d\n", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stdout, "[PROGRAM] Successfully forked a new child process"
|
||||
" with PID %d\n", ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int doclient(void) {
|
||||
int do_clt(void) {
|
||||
int ret = 0;
|
||||
int client_socket;
|
||||
struct sockaddr_in serv_addr;
|
||||
|
@ -510,11 +569,11 @@ int main(int argc, char *argv[]) {
|
|||
const char *mode = argv[1];
|
||||
ret = strcmp(mode, SERVER_MODE);
|
||||
if (ret == 0)
|
||||
return doserver();
|
||||
return do_srv();
|
||||
|
||||
ret = strcmp(mode, CLIENT_MODE);
|
||||
if (ret == 0)
|
||||
return doclient();
|
||||
return do_clt();
|
||||
|
||||
fprintf(stderr, "Unknown proxy mode\n");
|
||||
}
|
|
@ -9,11 +9,14 @@
|
|||
#define PROXY_PORT 2020
|
||||
#define PROXY_CONN 20
|
||||
#define PROXY_MAX_MSGLEN 10000*1024
|
||||
#define PROXY_DEF_PORT "80"
|
||||
#define PROXY_BASE_PORT 10
|
||||
|
||||
#define REGEX_MATCHN 4
|
||||
#define REGEX_TITLE "^([A-Z]+)[ ]+([a-zA-Z0-9\\:/_.,-]+)"\
|
||||
"[ ]+([a-zA-Z0-9_.,/-]+)[\n\r]*$"
|
||||
#define REGEX_HEADER "^([a-zA-Z0-9_-]*):[ \t]+([^\r\n]*)"
|
||||
#define REGEX_HOST "^([a-zA-Z0-9_/,.-]+)(:[0-9]+)?$"
|
||||
|
||||
#define CLIENT_MESSAGE "GET http://archive.0xdeadbeer.org/ HTTP/1.0\r\n\r\n"\
|
||||
"Host: archive.0xdeadbeer.org\r\n"\
|
||||
|
@ -33,6 +36,9 @@ struct header {
|
|||
};
|
||||
|
||||
struct request {
|
||||
char *host_name;
|
||||
char *host_port;
|
||||
|
||||
char *method;
|
||||
char *uri;
|
||||
char *ver;
|
Loading…
Reference in New Issue
Block a user