diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6c8da70 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.o +deps +jansson +libjwt +src/server +src/jwt_demo_hs256 +src/jwt_demo_rs256 +.gitignore diff --git a/src/Makefile b/src/Makefile index 62c46b1..48e2b71 100644 --- a/src/Makefile +++ b/src/Makefile @@ -11,7 +11,10 @@ LDLIBS=-L$(DEP_LIB_DIR) -ljwt -ljansson -lcrypto -ldl HEADERS=socket.h http.h hexdump.h buffer.h bufio.h OBJ=main.o socket.o hexdump.o http.o bufio.o -all: server + +OTHERS=jwt_demo_rs256 jwt_demo_hs256 + +all: server $(OTHERS) $(OBJ) : $(HEADERS) @@ -19,4 +22,4 @@ server: $(OBJ) $(CC) $(LDFLAGS) -o $@ $(OBJ) $(LDLIBS) clean: - /bin/rm $(OBJ) + /bin/rm $(OBJ) $(OTHERS) diff --git a/src/http.c b/src/http.c index a7c42e4..c01515d 100644 --- a/src/http.c +++ b/src/http.c @@ -34,19 +34,19 @@ char * server_root; // root from which static files are served /* Parse HTTP request line, setting req_method, req_path, and req_version. */ -static int +static bool http_parse_request(struct http_transaction *ta) { size_t req_offset; ssize_t len = bufio_readline(ta->client->bufio, &req_offset); if (len <= 0) - return len; + return false; char *request = bufio_offset2ptr(ta->client->bufio, req_offset); char *endptr; char *method = strtok_r(request, " ", &endptr); if (method == NULL) - return -1; + return false; if (!strcmp(method, "GET")) ta->req_method = HTTP_GET; @@ -57,37 +57,37 @@ http_parse_request(struct http_transaction *ta) char *req_path = strtok_r(NULL, " ", &endptr); if (req_path == NULL) - return -1; + return false; ta->req_path = bufio_ptr2offset(ta->client->bufio, req_path); char *http_version = strtok_r(NULL, CRLF, &endptr); if (http_version == NULL) // would be HTTP 0.9 - return -1; + return false; if (!strcmp(http_version, "HTTP/1.1")) ta->req_version = HTTP_1_1; else if (!strcmp(http_version, "HTTP/1.0")) ta->req_version = HTTP_1_0; else - return -1; + return false; - return 0; -} + return true; +} /* Process HTTP headers. */ -static int +static bool http_process_headers(struct http_transaction *ta) { for (;;) { size_t header_offset; ssize_t len = bufio_readline(ta->client->bufio, &header_offset); - char *header = bufio_offset2ptr(ta->client->bufio, header_offset); if (len <= 0) - return len; + return false; + char *header = bufio_offset2ptr(ta->client->bufio, header_offset); if (len == 2 && STARTS_WITH(header, CRLF)) // empty CRLF - return 0; + return true; header[len-2] = '\0'; /* Each header field consists of a name followed by a @@ -100,7 +100,7 @@ http_process_headers(struct http_transaction *ta) char *field_value = strtok_r(NULL, " \t", &endptr); // skip leading & trailing OWS if (field_name == NULL) - return -1; + return false; // printf("Header: %s: %s\n", field_name, field_value); if (!strcasecmp(field_name, "Content-Length")) { @@ -109,8 +109,6 @@ http_process_headers(struct http_transaction *ta) /* Handle other headers here. */ } - - return 0; } const int MAX_HEADER_LEN = 2048; @@ -331,16 +329,16 @@ http_handle_transaction(struct http_client *self) memset(&ta, 0, sizeof ta); ta.client = self; - if (http_parse_request(&ta) == -1) - return -1; + if (!http_parse_request(&ta)) + return false; - if (http_process_headers(&ta) == -1) - return -1; + if (!http_process_headers(&ta)) + return false; if (ta.req_content_len > 0) { int rc = bufio_read(self->bufio, ta.req_content_len, &ta.req_body); if (rc != ta.req_content_len) - return -1; + return false; // To see the body, use this: // char *body = bufio_offset2ptr(ta.client->bufio, ta.req_body); diff --git a/src/jwt_demo_hs256.c b/src/jwt_demo_hs256.c new file mode 100644 index 0000000..5b7845b --- /dev/null +++ b/src/jwt_demo_hs256.c @@ -0,0 +1,56 @@ +/* + * Quick demo of how to use libjwt using a HS256. + * + * @author gback, CS 3214, Spring 2018 + */ +#include +#include +#include +#include +#include + +static const char * NEVER_EMBED_A_SECRET_IN_CODE = "supa secret"; + +int +main() +{ + jwt_t *mytoken; + + if (jwt_new(&mytoken)) + perror("jwt_new"), exit(-1); + + if (jwt_add_grant(mytoken, "sub", "user0")) + perror("jwt_add_grant sub"), exit(-1); + + time_t now = time(NULL); + if (jwt_add_grant_int(mytoken, "iat", now)) + perror("jwt_add_grant iat"), exit(-1); + + if (jwt_add_grant_int(mytoken, "exp", now + 3600 * 24)) + perror("jwt_add_grant exp"), exit(-1); + + if (jwt_set_alg(mytoken, JWT_ALG_HS256, + (unsigned char *)NEVER_EMBED_A_SECRET_IN_CODE, strlen(NEVER_EMBED_A_SECRET_IN_CODE))) + perror("jwt_set_alg"), exit(-1); + + printf("dump:\n"); + if (jwt_dump_fp(mytoken, stdout, 1)) + perror("jwt_dump_fp"), exit(-1); + + char *encoded = jwt_encode_str(mytoken); + if (encoded == NULL) + perror("jwt_encode_str"), exit(-1); + + printf("encoded as %s\nTry entering this at jwt.io\n", encoded); + + jwt_t *ymtoken; + if (jwt_decode(&ymtoken, encoded, + (unsigned char *)NEVER_EMBED_A_SECRET_IN_CODE, strlen(NEVER_EMBED_A_SECRET_IN_CODE))) + perror("jwt_decode"), exit(-1); + + char *grants = jwt_get_grants_json(ymtoken, NULL); // NULL means all + if (grants == NULL) + perror("jwt_get_grants_json"), exit(-1); + + printf("redecoded: %s\n", grants); +} diff --git a/src/jwt_demo_rs256.c b/src/jwt_demo_rs256.c new file mode 100644 index 0000000..7d7d18e --- /dev/null +++ b/src/jwt_demo_rs256.c @@ -0,0 +1,74 @@ +/* + * Quick demo of how to use libjwt using a RS256. + * You must have created a private/public key pair like so: + * + * openssl genpkey -algorithm RSA -out myprivatekey.pem -pkeyopt rsa_keygen_bits:2048 + * openssl rsa -in myprivatekey.pem -pubout > mykey.pub + * + * @author gback, CS 3214, Spring 2018 + */ +#include +#include +#include +#include +#include + +unsigned char private_key[16384]; +unsigned char public_key[16384]; + +static void +read_key(unsigned char *key, const char *name) +{ + FILE *f = fopen(name, "r"); + if (f == NULL) + perror("fopen"), exit(-1); + size_t len = fread(key, 1, 8192, f); + key[len] = '\0'; + fclose(f); +} + +int +main() +{ + read_key(private_key, "myprivatekey.pem"); + read_key(public_key, "mykey.pub"); + + jwt_t *mytoken; + + if (jwt_new(&mytoken)) + perror("jwt_new"), exit(-1); + + if (jwt_add_grant(mytoken, "sub", "user0")) + perror("jwt_add_grant sub"), exit(-1); + + time_t now = time(NULL); + if (jwt_add_grant_int(mytoken, "iat", now)) + perror("jwt_add_grant iat"), exit(-1); + + if (jwt_add_grant_int(mytoken, "exp", now + 3600 * 24)) + perror("jwt_add_grant exp"), exit(-1); + + if (jwt_set_alg(mytoken, JWT_ALG_RS256, + private_key, strlen((char *)private_key))) + perror("jwt_set_alg"), exit(-1); + + printf("dump:\n"); + if (jwt_dump_fp(mytoken, stdout, 1)) + perror("jwt_dump_fp"), exit(-1); + + char *encoded = jwt_encode_str(mytoken); + if (encoded == NULL) + perror("jwt_encode_str"), exit(-1); + + printf("encoded as %s\nTry entering this at jwt.io\n", encoded); + + jwt_t *ymtoken; + if (jwt_decode(&ymtoken, encoded, public_key, strlen((char *)public_key))) + perror("jwt_decode"), exit(-1); + + char *grants = jwt_get_grants_json(ymtoken, NULL); // NULL means all + if (grants == NULL) + perror("jwt_get_grants_json"), exit(-1); + + printf("redecoded: %s\n", grants); +} diff --git a/src/login.html b/src/login.html new file mode 100644 index 0000000..7e540b1 --- /dev/null +++ b/src/login.html @@ -0,0 +1,41 @@ + + + + +
+ Username: + Password: + +
+
The result of the request will appear here.
+ + diff --git a/src/main.c b/src/main.c index 44c4cc2..11276fe 100644 --- a/src/main.c +++ b/src/main.c @@ -23,6 +23,7 @@ server_loop(char *port_string) { int accepting_socket = socket_open_bind_listen(port_string, 1024); for (;;) { + fprintf(stderr, "Waiting for client...\n"); int client_socket = socket_accept_client(accepting_socket); if (client_socket == -1) return;