128 lines
3.0 KiB
C
128 lines
3.0 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include <openssl/ssl.h>
|
|
#include <openssl/err.h>
|
|
|
|
#include "socketHelp.h"
|
|
|
|
/*
|
|
* This function turns a IPv4 four byte octet into
|
|
* an unsigned 32 bit integer which can be used when
|
|
* opening new socket connections
|
|
*/
|
|
uint32_t addr2sin_addr(char *addr) {
|
|
char *token;
|
|
int i = 0;
|
|
uint32_t addrNum = 0;
|
|
unsigned long addrTempNum = 0;
|
|
|
|
token = strtok(addr, ".");
|
|
while(token != NULL) {
|
|
addrTempNum = strtoul(token, NULL,10);
|
|
if ( addrTempNum > 255 ) { // Check if octet is valid
|
|
printf("Invalid IP octet: %ld\n", addrTempNum);
|
|
|
|
free(token);
|
|
return -1;
|
|
} // Adding value to addr number
|
|
addrNum = addrNum + ( addrTempNum << (8*(3-i)) );
|
|
|
|
token = strtok(NULL, ".");
|
|
i++;
|
|
}
|
|
|
|
free(token);
|
|
return addrNum;
|
|
}
|
|
|
|
SSL_CTX* InitServerCTX() {
|
|
const 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, uint32_t listenAddr,
|
|
SSL_CTX **ctx, char certFile[], char keyFile[]) {
|
|
|
|
SSL_library_init();
|
|
*ctx = InitServerCTX();
|
|
LoadCertificates(*ctx, certFile, keyFile);
|
|
|
|
if ( createSocket(port, server_fd, address, addrlen, listenAddr) ) {
|
|
fprintf(stderr, "Error create socket\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int createSocket(int port, int *server_fd, struct sockaddr_in *address, int *addrlen, uint32_t listenAddr) {
|
|
int opt = 1;
|
|
|
|
// Create socket fd
|
|
if ((*server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
|
|
perror("socket failed");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
// Attach socket to PORT
|
|
if (setsockopt(*server_fd, SOL_SOCKET, SO_REUSEADDR |SO_REUSEPORT,
|
|
&opt, sizeof(opt))) {
|
|
perror("Set socket opt failure");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
address->sin_family = AF_INET;
|
|
if (listenAddr != -1) { // Checking to see if listenAddr is passed
|
|
address->sin_addr.s_addr = htonl(listenAddr);
|
|
} else { // Default to any addr
|
|
address->sin_addr.s_addr = INADDR_ANY;
|
|
}
|
|
address->sin_port = htons (port);
|
|
|
|
// Attach to PORT
|
|
if (bind(*server_fd, (struct sockaddr *)address,
|
|
sizeof(*address))<0) {
|
|
perror("Failed to bind");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (listen(*server_fd, 3) < 0) {
|
|
perror("Failed to listen");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
return 0;
|
|
}
|