From: Jean-Marc Pigeon (Delson) Date: Mon, 5 Aug 2024 09:59:28 +0000 (-0400) Subject: starting to add unissl module X-Git-Tag: tag-0.4~21 X-Git-Url: https://jmp-git.ovh.safe.ca/?a=commitdiff_plain;h=bcb024be336fdd4a620196ae8a83c09868624736;p=jmp%2Fmailleur starting to add unissl module --- diff --git a/app/Makefile b/app/Makefile index 2dc36db..1996e6d 100644 --- a/app/Makefile +++ b/app/Makefile @@ -35,7 +35,9 @@ CC = gcc LD = gcc CFLAGS = -I ../lib -Wall $(OPTIME) LIBAI = ../lib/libAI.a -LIBS = $(LIBAI) +LIBS = $(LIBAI) \ + -lcrypto \ + #-------------------------------------------------------------------- #Dependances #-------------------------------------------------------------------- diff --git a/kleenex/Makefile b/kleenex/Makefile index 82dc6b1..b7a05d2 100644 --- a/kleenex/Makefile +++ b/kleenex/Makefile @@ -4,9 +4,12 @@ server : server.c memleak : memleak.c +openssl : openssl.c + clean : - @ rm -f server memleak + @ rm -f server memleak openssl @ rm -f *.o CFLAGS = -Wall -D_GNU_SOURCE -g -LDFLAGS = -g +LDFLAGS = -g +LDLIBS = -lssl -lcrypto diff --git a/kleenex/cert.pem b/kleenex/cert.pem new file mode 120000 index 0000000..bd4af63 --- /dev/null +++ b/kleenex/cert.pem @@ -0,0 +1 @@ +/etc/letsencrypt/live/devel5.safe.ca/fullchain.pem \ No newline at end of file diff --git a/kleenex/key.pem b/kleenex/key.pem new file mode 120000 index 0000000..c7e244c --- /dev/null +++ b/kleenex/key.pem @@ -0,0 +1 @@ +/etc/letsencrypt/live/devel5.safe.ca/privkey.pem \ No newline at end of file diff --git a/kleenex/openssl.c b/kleenex/openssl.c new file mode 100644 index 0000000..be4380b --- /dev/null +++ b/kleenex/openssl.c @@ -0,0 +1,374 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef enum { + CONTINUE, + BREAK, + NEITHER +} ACTION; + +ACTION ssl_connect(SSL* ssl, int* wants_tcp_write, int* connecting) { + printf("calling SSL_connect\n"); + + int result = SSL_connect(ssl); + if (result == 0) { + long error = ERR_get_error(); + const char* error_str = ERR_error_string(error, NULL); + printf("could not SSL_connect: %s\n", error_str); + return BREAK; + } else if (result < 0) { + int ssl_error = SSL_get_error(ssl, result); + if (ssl_error == SSL_ERROR_WANT_WRITE) { + printf("SSL_connect wants write\n"); + *wants_tcp_write = 1; + return CONTINUE; + } + + if (ssl_error == SSL_ERROR_WANT_READ) { + printf("SSL_connect wants read\n"); + // wants_tcp_read is always 1; + return CONTINUE; + } + + long error = ERR_get_error(); + const char* error_string = ERR_error_string(error, NULL); + printf("could not SSL_connect %s\n", error_string); + return BREAK; + } else { + printf("connected\n"); + *connecting = 0; + return CONTINUE; + } + + return NEITHER; +} + +ACTION ssl_read(SSL* ssl, int* wants_tcp_write, int* call_ssl_read_instead_of_write) { + printf("calling SSL_read\n"); + + *call_ssl_read_instead_of_write = 0; + + char buffer[1024]; + int num = SSL_read(ssl, buffer, sizeof(buffer)); + if (num == 0) { + long error = ERR_get_error(); + const char* error_str = ERR_error_string(error, NULL); + printf("could not SSL_read (returned 0): %s\n", error_str); + return BREAK; + } else if (num < 0) { + int ssl_error = SSL_get_error(ssl, num); + if (ssl_error == SSL_ERROR_WANT_WRITE) { + printf("SSL_read wants write\n"); + *wants_tcp_write = 1; + *call_ssl_read_instead_of_write = 1; + return CONTINUE; + } + + if (ssl_error == SSL_ERROR_WANT_READ) { + printf("SSL_read wants read\n"); + // wants_tcp_read is always 1; + return CONTINUE; + } + + long error = ERR_get_error(); + const char* error_string = ERR_error_string(error, NULL); + printf("could not SSL_read (returned -1) %s\n", error_string); + return BREAK; + } else { + printf("read %d bytes\n", num); + } + + return NEITHER; +} + +ACTION ssl_write(SSL* ssl, int* wants_tcp_write, int* call_ssl_write_instead_of_read, + int is_client, int should_start_a_new_write) { + printf("calling SSL_write\n"); + + static char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + static int to_write = 0; + if (!*call_ssl_write_instead_of_read && !to_write && is_client && should_start_a_new_write) { + to_write = 1024; + printf("decided to write %d bytes\n", to_write); + } + + if (*call_ssl_write_instead_of_read && !to_write) { + printf("ssl should not have requested a write from a read if no data was waiting to be written\n"); + return BREAK; + } + + *call_ssl_write_instead_of_read = 0; + + if (!to_write) { + return NEITHER; + } + + int num = SSL_write(ssl, buffer, to_write); + if (num == 0) { + long error = ERR_get_error(); + const char* error_str = ERR_error_string(error, NULL); + printf("could not SSL_write (returned 0): %s\n", error_str); + return BREAK; + } else if (num < 0) { + int ssl_error = SSL_get_error(ssl, num); + if (ssl_error == SSL_ERROR_WANT_WRITE) { + printf("SSL_write wants write\n"); + *wants_tcp_write = 1; + return CONTINUE; + } + + if (ssl_error == SSL_ERROR_WANT_READ) { + printf("SSL_write wants read\n"); + *call_ssl_write_instead_of_read = 1; + // wants_tcp_read is always 1; + return CONTINUE; + } + + long error = ERR_get_error(); + const char* error_string = ERR_error_string(error, NULL); + printf("could not SSL_write (returned -1): %s\n", error_string); + return BREAK; + } else { + printf("wrote %d of %d bytes\n", num, to_write); + if (to_write < num) { + *wants_tcp_write = 1; + } else { + *wants_tcp_write = 0; + } + to_write -= num; + } + + return NEITHER; +} + +int main(int argc, char** argv) { + if (argc != 2 || (strcmp(argv[1], "client") && strcmp(argv[1], "server"))) { + printf("need parameter 'client' or 'server'\n"); + return 1; + } + + int is_client = !strcmp(argv[1], "client"); + int port = 2000; + in_addr_t dest = 0x7f000001; + //int port = 465; + //in_addr_t dest = 0xc0DBFE2C; //clement.safe.ca + + SSL_library_init(); + SSL_load_error_strings(); + + SSL_CTX* ssl_ctx = SSL_CTX_new(is_client ? + SSLv23_client_method() : + SSLv23_server_method()); + if (!ssl_ctx) { + printf("could not SSL_CTX_new\n"); + return 1; + } + + int sockfd = 0; + if (is_client) { + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + printf("could not create socket\n"); + return 1; + } + } else { + const char* certificate; + + certificate="./cert.pem"; + if (SSL_CTX_use_certificate_file(ssl_ctx, certificate, SSL_FILETYPE_PEM) != 1) { + printf("could not SSL_CTX_use_certificate_file\n"); + return 1; + } + + certificate="./key.pem"; + if (SSL_CTX_use_PrivateKey_file(ssl_ctx, certificate, SSL_FILETYPE_PEM) != 1) { + printf("could not SSL_CTX_use_PrivateKey_file\n"); + return 1; + } + + int server = socket(AF_INET, SOCK_STREAM, 0); + if (server < 0) { + printf("could not create socket\n"); + return 1; + } + + int on = 1; + if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) { + close(server); + printf("could not setsockopt\n"); + return 1; + } + + // Bind on any interface. + struct sockaddr_in addr; + bzero(&addr, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + if (bind(server, (struct sockaddr*)(&addr), + sizeof(addr))) { + printf("could not bind\n"); + close(server); + return 1; + } + + if (listen(server, 1)) { + printf("could not listen\n"); + close(server); + return 1; + } + + sockfd = accept(server, NULL, NULL); + if (sockfd < 0) { + printf("could not create accept\n"); + return 1; + } + } + + SSL* ssl = SSL_new(ssl_ctx); + if (!ssl) { + printf("could not SSL_new\n"); + return 1; + } + + // Set the socket to be non blocking. + int flags = fcntl(sockfd, F_GETFL, 0); + if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK)) { + printf("could not fcntl\n"); + close(sockfd); + return 1; + } + + int one = 1; + if (setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) { + printf("could not setsockopt\n"); + close(sockfd); + return 1; + } + + if (is_client) { + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(dest); + + if (connect(sockfd, (struct sockaddr*)(&addr), sizeof(addr)) && errno != EINPROGRESS) { + printf("could not connect\n"); + return 1; + } + } + + if (!SSL_set_fd(ssl, sockfd)) { + close(sockfd); + printf("could not SSL_set_fd\n"); + return 1; + } + + int connecting = 1; + if (is_client) { + SSL_set_connect_state(ssl); + } else { + SSL_set_accept_state(ssl); + connecting = 0; + } + + fd_set read_fds, write_fds; + int wants_tcp_read = 1, wants_tcp_write = is_client; + int call_ssl_read_instead_of_write = 0; + int call_ssl_write_instead_of_read = 0; + + for (;;) { + printf("selecting\n"); + FD_ZERO(&read_fds); + FD_ZERO(&write_fds); + if (wants_tcp_read) { + FD_SET(sockfd, &read_fds); + } + + if (wants_tcp_write) { + FD_SET(sockfd, &write_fds); + } + + struct timeval timeout = { 1, 0 }; + + if (select(sockfd + 1, &read_fds, &write_fds, NULL, &timeout)) { + if (FD_ISSET(sockfd, &read_fds)) { + printf("readable\n"); + + if (connecting) { + ACTION action = ssl_connect(ssl, &wants_tcp_write, &connecting); + if (action == CONTINUE) { + continue; + } else if (action == BREAK) { + break; + } + } else { + ACTION action; + if (call_ssl_write_instead_of_read) { + action = ssl_write(ssl, &wants_tcp_write, &call_ssl_write_instead_of_read, is_client, 0); + } else { + action = ssl_read(ssl, &wants_tcp_write, &call_ssl_read_instead_of_write); + } + + if (action == CONTINUE) { + continue; + } else if (action == BREAK) { + break; + } + } + } + + if (FD_ISSET(sockfd, &write_fds)) { + printf("writable\n"); + + if (connecting) { + wants_tcp_write = 0; + + ACTION action = ssl_connect(ssl, &wants_tcp_write, &connecting); + if (action == CONTINUE) { + continue; + } else if (action == BREAK) { + break; + } + } else { + ACTION action; + if (call_ssl_read_instead_of_write) { + action = ssl_read(ssl, &wants_tcp_write, &call_ssl_read_instead_of_write); + } else { + action = ssl_write(ssl, &wants_tcp_write, &call_ssl_write_instead_of_read, is_client, 0); + } + + if (action == CONTINUE) { + continue; + } else if (action == BREAK) { + break; + } + } + } + } else if (is_client & !connecting && !call_ssl_write_instead_of_read) { + ACTION action = ssl_write(ssl, &wants_tcp_write, &call_ssl_write_instead_of_read, is_client, 1); + if (action == CONTINUE) { + continue; + } else if (action == BREAK) { + break; + } + } + } + + SSL_CTX_free(ssl_ctx); + + return 0; +} diff --git a/lib/Makefile b/lib/Makefile index 34f5988..a7e2650 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -20,7 +20,7 @@ OBJS= \ gestcp.o \ devsoc.o \ unieml.o \ - unipar.o uniprc.o unisig.o \ + unipar.o uniprc.o unisig.o unissl.o \ subrou.o objs : $(OBJS) @@ -62,6 +62,10 @@ unisig.o: \ subrou.h \ unisig.h unisig.c +unissl.o: \ + subrou.h \ + unissl.h unissl.c + subrou.o: \ subrou.h subrou.c diff --git a/lib/devsoc.c b/lib/devsoc.c index 4ef2b83..aefaf7c 100644 --- a/lib/devsoc.c +++ b/lib/devsoc.c @@ -17,6 +17,7 @@ #include "subrou.h" #include "uniprc.h" +#include "unissl.h" #include "devsoc.h" //Need to have GNU_SOURCE define within CFLAGS @@ -444,8 +445,10 @@ if (mode!=modopen) { case true : (void) rou_modesubrou(mode); (void) prc_modeuniprc(mode); + (void) ssl_modeunissl(mode); break; case false : + (void) ssl_modeunissl(mode); (void) prc_modeuniprc(mode); (void) rou_modesubrou(mode); break; diff --git a/lib/modrec.c b/lib/modrec.c index 8b08397..977646e 100644 --- a/lib/modrec.c +++ b/lib/modrec.c @@ -229,9 +229,9 @@ _Bool proceed; childs=(pid_t)0; bindings=(SOCPTR **)0; -bindings=soc_mkbindinf(bindings,pro_smtp,"192.219.254.70","25",3); -bindings=soc_mkbindinf(bindings,pro_smtp,"127.0.0.1","2525",3); -bindings=soc_mkbindinf(bindings,pro_smtp,"127.0.0.26","2626",1); +bindings=soc_mkbindinf(bindings,pro_smtp,"192.219.254.70","1025",3); +bindings=soc_mkbindinf(bindings,pro_smtp,"192.219.254.70","1465",3); +bindings=soc_mkbindinf(bindings,pro_smtp,"192.219.254.70","1587",3); nbrbind=rou_nbrlist((void **)bindings); phase=0; proceed=true; diff --git a/lib/subrou.c b/lib/subrou.c index 9e7e532..acab7e2 100644 --- a/lib/subrou.c +++ b/lib/subrou.c @@ -20,7 +20,7 @@ //version definition #define VERSION "0.3" -#define RELEASE "20" +#define RELEASE "21" //Public variables PUBLIC int debug=0; //debug level diff --git a/lib/subrou.h b/lib/subrou.h index 7efcd65..68a94a8 100644 --- a/lib/subrou.h +++ b/lib/subrou.h @@ -10,6 +10,7 @@ #include #include #include +#include #define APPNAME "maild" //application name diff --git a/lib/unissl.c b/lib/unissl.c new file mode 100644 index 0000000..ae802bc --- /dev/null +++ b/lib/unissl.c @@ -0,0 +1,55 @@ +// vim: smarttab tabstop=8 shiftwidth=2 expandtab +/********************************************************/ +/* */ +/* Implement all routine to manage SMTP low level */ +/* exchange. */ +/* */ +/********************************************************/ +#include +#include +#include +#include + +#include "subrou.h" +#include "unissl.h" + +static _Bool modopen; //module open/close status + +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to "open/close" module and do */ +/* homework purpose */ +/* return zero if everything right */ +/* */ +/********************************************************/ +int ssl_modeunissl(_Bool mode) + +{ +#define OPEP "unidoc.c:soc_modeunisoc" + +int status; + +status=0; +if (mode!=modopen) { + (void) rou_modesubrou(mode); + switch ((int)mode) { + case true : + OPENSSL_init_ssl(0, NULL); + ERR_clear_error(); + break; + case false : + break; + default : + (void) fprintf(stderr,"Calling %s with wrong mode='%d' (Bug?!):", + OPEP,(int)mode); + status=-1; + break; + } + modopen=mode; + } +return status; +#undef OPEP +} diff --git a/lib/unissl.h b/lib/unissl.h new file mode 100644 index 0000000..ef8d25b --- /dev/null +++ b/lib/unissl.h @@ -0,0 +1,13 @@ +// vim: smarttab tabstop=8 shiftwidth=2 expandtab +/********************************************************/ +/* */ +/* Define all routine to manage SSL connexion */ +/* */ +/********************************************************/ +#ifndef UNISSL +#define UNISSL + +//homework to be done before starting/stopping module. +extern int ssl_modeunissl(_Bool mode); + +#endif