Implemented basic SSL
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @@ -8,7 +8,7 @@ packages: | |||||||
| compile: | compile: | ||||||
| 	@echo "Compiling..." | 	@echo "Compiling..." | ||||||
| 	@mkdir -p bin | 	@mkdir -p bin | ||||||
| 	gcc src/necronda-server.c -o bin/necronda-server -std=c11 -D_POSIX_C_SOURCE | 	gcc src/necronda-server.c -o bin/necronda-server -std=c11 -D_POSIX_C_SOURCE -lssl -lcrypto | ||||||
| 	@echo "Finished compiling!" | 	@echo "Finished compiling!" | ||||||
|  |  | ||||||
| install: | packages update compile | install: | packages update compile | ||||||
|   | |||||||
							
								
								
									
										39
									
								
								src/client.c
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								src/client.c
									
									
									
									
									
								
							| @@ -40,27 +40,34 @@ int client_request_handler() { | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int client_connection_handler(int client) { | int client_connection_handler(sock *client) { | ||||||
|     char buf1[256]; |     int ret; | ||||||
|     char buf2[256]; |  | ||||||
|     print("Connection accepted from %s (%s) [%s]", client_addr_str, client_addr_str, "N/A"); |     print("Connection accepted from %s (%s) [%s]", client_addr_str, client_addr_str, "N/A"); | ||||||
|  |  | ||||||
|     sprintf(buf1, "Hello World!\nYour address is: %s\n", client_addr_str); |     if (client->enc) { | ||||||
|     send(client, buf1, strlen(buf1), 0); |         client->ssl = SSL_new(client->ctx); | ||||||
|     int len = -1; |         SSL_set_fd(client->ssl, client->socket); | ||||||
|     while (len == -1) { |  | ||||||
|         len = recv(client, &buf1, sizeof(buf1), 0); |  | ||||||
|     } |  | ||||||
|     sprintf(buf2, "Thank you, %.*s!\nGood bye!\n", len, buf1); |  | ||||||
|     send(client, buf2, strlen(buf2), 0); |  | ||||||
|  |  | ||||||
|     close(client); |         ret = SSL_accept(client->ssl); | ||||||
|  |         if (ret <= 0) { | ||||||
|  |             print(ERR_STR "Unable to perform handshake: %s" CLR_STR, ssl_get_error(client->ssl, ret)); | ||||||
|  |             goto close; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     close: | ||||||
|  |     if (client->enc) { | ||||||
|  |         SSL_shutdown(client->ssl); | ||||||
|  |     } | ||||||
|  |     shutdown(client->socket, SHUT_RDWR); | ||||||
|  |     close(client->socket); | ||||||
|  |  | ||||||
|     print("Connection closed"); |     print("Connection closed"); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int client_handler(int client, long client_num, struct sockaddr_in6 *client_addr) { | int client_handler(sock *client, long client_num, struct sockaddr_in6 *client_addr) { | ||||||
|  |     int ret; | ||||||
|     struct sockaddr_in6 *server_addr; |     struct sockaddr_in6 *server_addr; | ||||||
|     struct sockaddr_storage server_addr_storage; |     struct sockaddr_storage server_addr_storage; | ||||||
|  |  | ||||||
| @@ -78,7 +85,7 @@ int client_handler(int client, long client_num, struct sockaddr_in6 *client_addr | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     socklen_t len = sizeof(server_addr_storage); |     socklen_t len = sizeof(server_addr_storage); | ||||||
|     getsockname(client, (struct sockaddr *) &server_addr_storage, &len); |     getsockname(client->socket, (struct sockaddr *) &server_addr_storage, &len); | ||||||
|     server_addr = (struct sockaddr_in6 *) &server_addr_storage; |     server_addr = (struct sockaddr_in6 *) &server_addr_storage; | ||||||
|     server_addr_str_ptr = malloc(INET6_ADDRSTRLEN); |     server_addr_str_ptr = malloc(INET6_ADDRSTRLEN); | ||||||
|     inet_ntop(server_addr->sin6_family, (void *) &server_addr->sin6_addr, server_addr_str_ptr, INET6_ADDRSTRLEN); |     inet_ntop(server_addr->sin6_family, (void *) &server_addr->sin6_addr, server_addr_str_ptr, INET6_ADDRSTRLEN); | ||||||
| @@ -90,10 +97,10 @@ int client_handler(int client, long client_num, struct sockaddr_in6 *client_addr | |||||||
|  |  | ||||||
|     log_base_prefix = malloc(256); |     log_base_prefix = malloc(256); | ||||||
|     sprintf(log_base_prefix, "[%24s][%s%4i%s]%s[%*s][%5i]%s ", |     sprintf(log_base_prefix, "[%24s][%s%4i%s]%s[%*s][%5i]%s ", | ||||||
|             server_addr_str, R_STR, ntohs(server_addr->sin6_port), CLR_STR, |             server_addr_str, client->enc ? HTTPS_STR : HTTP_STR, ntohs(server_addr->sin6_port), CLR_STR, | ||||||
|             color_table[client_num % 6], INET_ADDRSTRLEN, client_addr_str, ntohs(client_addr->sin6_port), CLR_STR); |             color_table[client_num % 6], INET_ADDRSTRLEN, client_addr_str, ntohs(client_addr->sin6_port), CLR_STR); | ||||||
|  |  | ||||||
|     int ret = client_connection_handler(client); |     ret = client_connection_handler(client); | ||||||
|     free(client_addr_str_ptr); |     free(client_addr_str_ptr); | ||||||
|     free(server_addr_str_ptr); |     free(server_addr_str_ptr); | ||||||
|     free(log_base_prefix); |     free(log_base_prefix); | ||||||
|   | |||||||
| @@ -24,6 +24,47 @@ | |||||||
|  |  | ||||||
| int active = 1; | int active = 1; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void openssl_init() { | ||||||
|  |     SSL_library_init(); | ||||||
|  |     SSL_load_error_strings(); | ||||||
|  |     ERR_load_BIO_strings(); | ||||||
|  |     OpenSSL_add_all_algorithms(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *ssl_get_error(SSL *ssl, int ret) { | ||||||
|  |     if (ret > 0) { | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     unsigned long ret2 = ERR_get_error(); | ||||||
|  |     char *err2 = strerror(errno); | ||||||
|  |     char *err1 = (char *) ERR_reason_error_string(ret2); | ||||||
|  |  | ||||||
|  |     switch (SSL_get_error(ssl, ret)) { | ||||||
|  |         case SSL_ERROR_NONE: | ||||||
|  |             return "none"; | ||||||
|  |         case SSL_ERROR_ZERO_RETURN: | ||||||
|  |             return "closed"; | ||||||
|  |         case SSL_ERROR_WANT_READ: | ||||||
|  |             return "want read"; | ||||||
|  |         case SSL_ERROR_WANT_WRITE: | ||||||
|  |             return "want write"; | ||||||
|  |         case SSL_ERROR_WANT_CONNECT: | ||||||
|  |             return "want connect"; | ||||||
|  |         case SSL_ERROR_WANT_ACCEPT: | ||||||
|  |             return "want accept"; | ||||||
|  |         case SSL_ERROR_WANT_X509_LOOKUP: | ||||||
|  |             return "want x509 lookup"; | ||||||
|  |         case SSL_ERROR_SYSCALL: | ||||||
|  |             return ((ret2 == 0) ? ((ret == 0) ? "protocol violation" : err2) : err1); | ||||||
|  |         case SSL_ERROR_SSL: | ||||||
|  |             return err1; | ||||||
|  |         default: | ||||||
|  |             return "unknown error"; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| void destroy() { | void destroy() { | ||||||
|     fprintf(stderr, "\n" ERR_STR "Terminating forcefully!" CLR_STR "\n"); |     fprintf(stderr, "\n" ERR_STR "Terminating forcefully!" CLR_STR "\n"); | ||||||
|     int status = 0; |     int status = 0; | ||||||
| @@ -97,7 +138,8 @@ int main(int argc, const char *argv[]) { | |||||||
|     int ready_sockets_num = 0; |     int ready_sockets_num = 0; | ||||||
|     long client_num = 0; |     long client_num = 0; | ||||||
|  |  | ||||||
|     int client; |     int client_fd; | ||||||
|  |     sock client; | ||||||
|     struct sockaddr_in6 client_addr; |     struct sockaddr_in6 client_addr; | ||||||
|     unsigned int client_addr_len = sizeof(client_addr); |     unsigned int client_addr_len = sizeof(client_addr); | ||||||
|  |  | ||||||
| @@ -139,7 +181,24 @@ int main(int argc, const char *argv[]) { | |||||||
|     signal(SIGINT, terminate); |     signal(SIGINT, terminate); | ||||||
|     signal(SIGTERM, terminate); |     signal(SIGTERM, terminate); | ||||||
|  |  | ||||||
|     // TODO implement TLS server side handshake |     openssl_init(); | ||||||
|  |  | ||||||
|  |     client.ctx = SSL_CTX_new(TLS_server_method()); | ||||||
|  |     SSL_CTX_set_options(client.ctx, SSL_OP_SINGLE_DH_USE); | ||||||
|  |     SSL_CTX_set_verify(client.ctx, SSL_VERIFY_NONE, NULL); | ||||||
|  |     SSL_CTX_set_min_proto_version(client.ctx, TLS1_VERSION); | ||||||
|  |     SSL_CTX_set_mode(client.ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); | ||||||
|  |     SSL_CTX_set_cipher_list(client.ctx, "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4"); | ||||||
|  |     SSL_CTX_set_ecdh_auto(client.ctx, 1); | ||||||
|  |  | ||||||
|  |     if (SSL_CTX_use_certificate_chain_file(client.ctx, "/home/lorenz/cert/chakotay.pem") != 1) { | ||||||
|  |         fprintf(stderr, ERR_STR "Unable to load certificate chain file: %s" CLR_STR "\n", ERR_reason_error_string(ERR_get_error())); | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     if (SSL_CTX_use_PrivateKey_file(client.ctx, "/home/lorenz/cert/priv/chakotay.key", SSL_FILETYPE_PEM) != 1) { | ||||||
|  |         fprintf(stderr, ERR_STR "Unable to load private key file: %s" CLR_STR "\n", ERR_reason_error_string(ERR_get_error())); | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     for (int i = 0; i < NUM_SOCKETS; i++) { |     for (int i = 0; i < NUM_SOCKETS; i++) { | ||||||
|         if (listen(SOCKETS[i], LISTEN_BACKLOG) == -1) { |         if (listen(SOCKETS[i], LISTEN_BACKLOG) == -1) { | ||||||
| @@ -168,8 +227,8 @@ int main(int argc, const char *argv[]) { | |||||||
|  |  | ||||||
|         for (int i = 0; i < NUM_SOCKETS; i++) { |         for (int i = 0; i < NUM_SOCKETS; i++) { | ||||||
|             if (FD_ISSET(SOCKETS[i], &read_socket_fds)) { |             if (FD_ISSET(SOCKETS[i], &read_socket_fds)) { | ||||||
|                 client = accept(SOCKETS[i], (struct sockaddr *) &client_addr, &client_addr_len); |                 client_fd = accept(SOCKETS[i], (struct sockaddr *) &client_addr, &client_addr_len); | ||||||
|                 if (client == -1) { |                 if (client_fd == -1) { | ||||||
|                     fprintf(parent_stderr, ERR_STR "Unable to accept connection: %s" CLR_STR "\n", strerror(errno)); |                     fprintf(parent_stderr, ERR_STR "Unable to accept connection: %s" CLR_STR "\n", strerror(errno)); | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
| @@ -179,11 +238,15 @@ int main(int argc, const char *argv[]) { | |||||||
|                     // child |                     // child | ||||||
|                     signal(SIGINT, SIG_IGN); |                     signal(SIGINT, SIG_IGN); | ||||||
|                     signal(SIGTERM, SIG_IGN); |                     signal(SIGTERM, SIG_IGN); | ||||||
|                     return client_handler(client, client_num, &client_addr); |  | ||||||
|  |                     client.socket = client_fd; | ||||||
|  |                     client.enc = i == 1; | ||||||
|  |  | ||||||
|  |                     return client_handler(&client, client_num, &client_addr); | ||||||
|                 } else if (pid > 0) { |                 } else if (pid > 0) { | ||||||
|                     // parent |                     // parent | ||||||
|                     client_num++; |                     client_num++; | ||||||
|                     close(client); |                     close(client_fd); | ||||||
|                     for (int j = 0; j < MAX_CHILDREN; j++) { |                     for (int j = 0; j < MAX_CHILDREN; j++) { | ||||||
|                         if (CHILDREN[j] == 0) { |                         if (CHILDREN[j] == 0) { | ||||||
|                             CHILDREN[j] = pid; |                             CHILDREN[j] = pid; | ||||||
|   | |||||||
| @@ -10,6 +10,13 @@ | |||||||
|  |  | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  | #include <openssl/bio.h> | ||||||
|  | #include <openssl/err.h> | ||||||
|  | #include <openssl/pem.h> | ||||||
|  | #include <openssl/ssl.h> | ||||||
|  | #include <openssl/conf.h> | ||||||
|  | #include <openssl/engine.h> | ||||||
|  | #include <openssl/dh.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| #define NUM_SOCKETS 2 | #define NUM_SOCKETS 2 | ||||||
| @@ -18,13 +25,23 @@ | |||||||
|  |  | ||||||
| #define ERR_STR "\x1B[1;31m" | #define ERR_STR "\x1B[1;31m" | ||||||
| #define CLR_STR "\x1B[0m" | #define CLR_STR "\x1B[0m" | ||||||
| #define R_STR "\x1B[31m" | #define HTTP_STR "\x1B[1;31m" | ||||||
| #define G_STR "\x1B[32m" | #define HTTPS_STR "\x1B[1;32m" | ||||||
|  |  | ||||||
| int SOCKETS[NUM_SOCKETS]; | int SOCKETS[NUM_SOCKETS]; | ||||||
| pid_t CHILDREN[MAX_CHILDREN]; | pid_t CHILDREN[MAX_CHILDREN]; | ||||||
|  |  | ||||||
| FILE *parent_stdout, *parent_stderr; | FILE *parent_stdout, *parent_stderr; | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     int enc:1; | ||||||
|  |     int socket; | ||||||
|  |     SSL_CTX *ctx; | ||||||
|  |     SSL *ssl; | ||||||
|  |     BIO *bio_in; | ||||||
|  |     BIO *bio_out; | ||||||
|  | } sock; | ||||||
|  |  | ||||||
|  | char *ssl_get_error(SSL *ssl, int ret); | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_NECRONDA_SERVER_H | #endif //NECRONDA_SERVER_NECRONDA_SERVER_H | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user