added ssl

This commit is contained in:
Pin
2022-02-17 23:22:30 -05:00
parent 5c60a475e7
commit 1c083b90f8
8 changed files with 300 additions and 25 deletions

View File

@@ -1,4 +1,4 @@
LIBRARIES = -Iinclude
LIBRARIES = `pkg-config --libs openssl` -Iinclude
SOURCES = ./src/* ./cmd/server.c
OUTPUT_DIR = ./bin
OUTPUT = -o ${OUTPUT_DIR}/PROG
@@ -18,11 +18,20 @@ output_dir:
CERT_DIR = ./certs/
genCerts:
mkdir -p ${CERT_DIR}
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
-x509 -nodes -days 365 -out ${CERT_DIR}cert.pem -keyout ${CERT_DIR}cert.pem \
-subj "/C=US/ST=Some-State/L=[]/O=[]/CN=localhost"
clean:
rm -rf $(OUTPUT_DIR) ${CERT_DIR} **.h.gch
genCerts:
mkdir -p ${CERT_DIR}
touch ${CERT_DIR}index.txt
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
-sha256 -nodes -out ${CERT_DIR}cacert.pem -keyout ${CERT_DIR}cakey.pem \
-outform PEM -subj "/C=US/ST=Some-State/L=[]/O=[]/CN=localhost"
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
-nodes -days 365 -out ${CERT_DIR}cert.csr -keyout ${CERT_DIR}key.pem \
-subj "/C=US/ST=Some-State/L=[]/O=[]/CN=localhost"
openssl ca -policy signing_policy -extensions signing_req \
-cert ./certs/cacert.pem -keyfile ./certs/cakey.pem \
-rand_serial -config ./ca/ca.cnf \
-out ./certs/cert.pem -infiles ./certs/cert.csr

87
ca/ca.cnf Normal file
View File

@@ -0,0 +1,87 @@
HOME = .
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
[ CA_default ]
base_dir = ./certs
certificate = $base_dir/cacert.pem # The CA certifcate
private_key = $base_dir/cakey.pem # The CA private key
new_certs_dir = $base_dir # Location for new certs after signing
database = $base_dir/index.txt # Database index file
serial = $base_dir/serial.txt # The current serial number
unique_subject = no # Set to 'no' to allow creation of
# several certificates with same subject.
default_days = 1000 # How long to certify for
default_crl_days = 30 # How long before next CRL
default_md = sha256 # Use public key default MD
preserve = no # Keep passed DN ordering
x509_extensions = ca_extensions # The extensions to add to the cert
email_in_dn = no # Don't concat the email in the DN
copy_extensions = copy # Required to copy SANs from CSR to cert
####################################################################
[ req ]
default_bits = 4096
default_keyfile = cakey.pem
distinguished_name = ca_distinguished_name
x509_extensions = ca_extensions
string_mask = utf8only
####################################################################
[ ca_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Maryland
localityName = Locality Name (eg, city)
localityName_default = Baltimore
organizationName = Organization Name (eg, company)
organizationName_default = Test CA, Limited
organizationalUnitName = Organizational Unit (eg, division)
organizationalUnitName_default = Server Research Department
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = Test CA
emailAddress = Email Address
emailAddress_default = test@example.com
####################################################################
[ ca_extensions ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer
basicConstraints = critical, CA:true
keyUsage = keyCertSign, cRLSign
####################################################################
[ alternate_names ]
DNS.1 = localhost
IP.1 = 127.0.0.1
####################################################################
[ signing_policy ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ signing_req ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment

View File

@@ -2,18 +2,29 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <openssl/ssl.h>
// Local Includes
#include "httpStruct.h"
#include "socketHelp.h"
#include "returnRequest.h"
#include "server.h"
#define PORT 8080
static int verbose_flag = 0;
bool enableHTTPS = 0;
int printDebug(char message[]) {
if (verbose_flag == 1) {
printf("[Debug] %s\n", message);
}
return 0;
}
int parseHTTPRequest(char buffer[], struct HTTPRequest *r) {
char temp[1];
char temp[1]; // Used to check newlines
char *token = calloc(8, sizeof(char));
int line = 0;
char *checkLine = calloc(1000, sizeof(char));;
@@ -63,29 +74,112 @@ int parseHTTPRequest(char buffer[], struct HTTPRequest *r) {
return 0;
}
int handleRequest(char buffer[], int socket) {
int handleRequest(char buffer[], int socket, SSL *ssl) {
struct HTTPRequest r; // Holds relevant HTTP request information
int checkerr = 0;
printDebug("Received Request");
// Grabbing relevant information out of request
checkerr = parseHTTPRequest(buffer, &r);
if (checkerr != 0) { // Checking for HTTP parsing error
printf("Error parsing: exit code %d\n", checkerr);
return return404Request(socket);
return return404Request(socket, ssl);
}
// Return response to socket
return200Request(socket);
return200Request(socket, ssl);
return 0;
}
int main(int argc, char const *argv[]) {
int main(int argc, char **argv) {
struct sockaddr_in address;
int server_fd, new_socket;
int checkerr = 0;
int port = 0; // Define what port server listens on
int checkerr = 0; // Used for error checking
int addrlen = sizeof(address);
char *certFile = malloc(0);
char *privKeyFile = malloc(0);
SSL_CTX *ctx = NULL;
char buffer[1024] = {};
checkerr = createSocket(PORT, &server_fd, &address, &addrlen);
// Setting up options
static const struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"port", required_argument, NULL, 'p'},
{"cert", required_argument, NULL, 'c'},
{"privkey", required_argument, NULL, 'k'},
{"verbose", no_argument, &verbose_flag, 1},
{0, 0, 0, 0}
};
const char* usage =
"Usage: seaweb [options]\n\n"
" -h --help\t\t\tShows this message\n"
" -p --port\t\t\tStarts webserver on passed port\n"
" -c --cert\t\t\tPath to certificate\n"
" -k --privkey\t\t\tPath to private key\n"
"\n"
"\n"
" --verbose\t\t\tPrints debug messages\n"
"\n";
int c;
while (1) {
int option_index = 0;
c = getopt_long(argc, argv, "hp:c:k:", long_options, &option_index);
if(c == -1) { // Break if no more options are present to parse
break;
}
switch(c) {
case 'h':
printf("%s", usage);
exit(EXIT_SUCCESS);
case 'p':
sscanf(optarg, "%d", &port);
break;
case 'c':
certFile = calloc(strlen(optarg), sizeof(char));
strcpy(certFile, optarg);
printf("Cert: %s\n", certFile);
break;
case 'k':
privKeyFile = calloc(strlen(optarg), sizeof(char));
strcpy(privKeyFile, optarg);
printf("Priv: %s\n", privKeyFile);
break;
}
}
// Argument checks
if (port == 0) { // Setting default port if none is passed
port = 8080;
}
if (!((strlen(certFile) > 0) == (strlen(privKeyFile) > 0))) { // XNOR of string lengths
// Checking what flag was not passed
if (strlen(certFile)) { // Privkey not passed
printf("If certificate file is specified, a private key files needs to be specified\n");
} else if (strlen(privKeyFile)) { // Cert not passed
printf("If privkey file is specified, a certificate files needs to be specified\n");
}
printf("Exiting...\n");
exit(EXIT_FAILURE);
} else if ( (strlen(certFile) > 0) && (strlen(privKeyFile) > 0) ) { // Enabling HTTPS
enableHTTPS = 1;
}
if ( enableHTTPS == 1 ) {
printf("Opening secure socket on port: %d\n", port);
checkerr = createSecureSocket(port, &server_fd, &address, &addrlen, &ctx, certFile, privKeyFile);
if ( ctx == NULL ) {
printf("Error creating ctx\n");
}
} else {
printf("Opening socket on port: %d\n", port);
checkerr = createSocket(port, &server_fd, &address, &addrlen);
}
if (checkerr != 0) {
perror("Error creating socket");
@@ -99,10 +193,23 @@ int main(int argc, char const *argv[]) {
perror("Accept connection error");
exit(EXIT_FAILURE);
}
read(new_socket, buffer, 1024);
handleRequest(buffer, new_socket);
if ( enableHTTPS ) {
SSL *ssl;
ssl = SSL_new(ctx);
SSL_set_fd(ssl, new_socket);
SSL_accept(ssl);
SSL_read(ssl, buffer, sizeof(buffer));
handleRequest(buffer, new_socket, ssl);
} else {
read(new_socket, buffer, 1024);
handleRequest(buffer, new_socket, NULL);
}
close(new_socket);
}
free(privKeyFile);
free(certFile);
close(server_fd);
exit(EXIT_SUCCESS);
}

View File

@@ -1,3 +1,5 @@
#include <openssl/ssl.h>
int returnRequest(int socket, char *message, int status);
int return200Request(int socket);
int return404Request(int socket);
int return200Request(int socket, SSL *ssl);
int return404Request(int socket, SSL *ssl);

4
include/server.h Normal file
View File

@@ -0,0 +1,4 @@
#include <stdbool.h>
extern bool enableHTTPS;

View File

@@ -1,5 +1,7 @@
#include <stdio.h>
#include <netinet/in.h>
#include <openssl/ssl.h>
int createSocket(int port, int *server_fd, struct sockaddr_in *address, int *addrlen);
int createSecureSocket(int port, int *server_fd, struct sockaddr_in *address, int *addrlen, SSL_CTX **ctx, char certFile[], char keyFile[]);

View File

@@ -1,18 +1,29 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <openssl/ssl.h>
int returnRequest(int socket, char *message, int status) {
send(socket, message, strlen(message), 0);
#include "server.h"
int returnRequest(int socket, char *message, int status, SSL *ssl) {
if ( enableHTTPS ) {
SSL_write(ssl, message, strlen(message));
SSL_get_fd(ssl);
SSL_free(ssl);
} else {
send(socket, message, strlen(message), 0);
}
return 0;
}
int return200Request(int socket) {
int return200Request(int socket, SSL *ssl) {
char *message = "HTTP/1.1 200 OK\nContent-Length: 6\nConnection: close\n\nhello\n";
return returnRequest(socket, message, 200);
return returnRequest(socket, message, 200, ssl);
}
int return404Request(int socket) {
int return404Request(int socket, SSL *ssl) {
char *message = "HTTP/1.1 404 Not Found\nContent-Length: 12\nConnection: close\n\n404 Request\n";
return returnRequest(socket, message, 400);
return returnRequest(socket, message, 400, ssl);
}

View File

@@ -3,6 +3,59 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "socketHelp.h"
SSL_CTX* InitServerCTX() {
SSL_METHOD *method;
SSL_CTX *ctx;
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
method = TLS_server_method();
ctx = SSL_CTX_new(method);
if ( ctx == NULL ) {
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
return ctx;
}
void LoadCertificates(SSL_CTX* ctx, char* certFile, char* keyFile) {
// Set local certificate from certFile
if ( SSL_CTX_use_certificate_file(ctx, certFile, SSL_FILETYPE_PEM) <= 0 ) {
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
// Set local priv key from keyFile
if ( SSL_CTX_use_PrivateKey_file(ctx, keyFile, SSL_FILETYPE_PEM) <=0 ) {
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
// Verify priv key
if ( !SSL_CTX_check_private_key(ctx) ) {
fprintf(stderr, "Private key does not match passed certificate file\n");
exit(EXIT_FAILURE);
}
return;
}
int createSecureSocket(int port, int *server_fd, struct sockaddr_in *address, int *addrlen, SSL_CTX **ctx, char certFile[], char keyFile[]) {
SSL_library_init();
*ctx = InitServerCTX();
LoadCertificates(*ctx, certFile, keyFile);
if ( createSocket(port, server_fd, address, addrlen) ) {
fprintf(stderr, "Error create socket\n");
exit(EXIT_FAILURE);
}
return 0;
}
int createSocket(int port, int *server_fd, struct sockaddr_in *address, int *addrlen) {
int opt = 1;