]> SAFE projects GIT repository - jmp/mailleur/commitdiff
starting to add unissl module
authorJean-Marc Pigeon (Delson) <jmp@safe.ca>
Mon, 5 Aug 2024 09:59:28 +0000 (05:59 -0400)
committerJean-Marc Pigeon (Delson) <jmp@safe.ca>
Mon, 5 Aug 2024 09:59:28 +0000 (05:59 -0400)
12 files changed:
app/Makefile
kleenex/Makefile
kleenex/cert.pem [new symlink]
kleenex/key.pem [new symlink]
kleenex/openssl.c [new file with mode: 0644]
lib/Makefile
lib/devsoc.c
lib/modrec.c
lib/subrou.c
lib/subrou.h
lib/unissl.c [new file with mode: 0644]
lib/unissl.h [new file with mode: 0644]

index 2dc36db5f26c467382b5ba78c253b0cbcd9774bb..1996e6d09cefea6651f25ef0a2315b150c8a96a8 100644 (file)
@@ -35,7 +35,9 @@ CC    =  gcc
 LD     =  gcc
 CFLAGS =  -I ../lib -Wall $(OPTIME)
 LIBAI  =  ../lib/libAI.a
-LIBS   =  $(LIBAI) 
+LIBS   =       $(LIBAI)                        \
+               -lcrypto                        \
+
 #--------------------------------------------------------------------
 #Dependances
 #--------------------------------------------------------------------
index 82dc6b172b098a2d255ec6c50f8303e1c3ac811e..b7a05d2b500e02191603257cf06541ff20297744 100644 (file)
@@ -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 (symlink)
index 0000000..bd4af63
--- /dev/null
@@ -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 (symlink)
index 0000000..c7e244c
--- /dev/null
@@ -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 (file)
index 0000000..be4380b
--- /dev/null
@@ -0,0 +1,374 @@
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <openssl/ssl.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+#include <sys/select.h>
+#include <netinet/in.h>
+
+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;
+}
index 34f5988d981346875d85e4337b489f407aaca0c1..a7e2650a2ff84bff420d7b05795b3e5a95ddf075 100644 (file)
@@ -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
 
index 4ef2b83a4c66235f5ddb92f713212c5b9e5f2eb3..aefaf7cd10fbd8b2227febb77227850b15b3ddf9 100644 (file)
@@ -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;
index 8b083978961ef9a4b0df8b343a32fc6771d779f8..977646eb1debea6f6f3a59c767771418f4abf491 100644 (file)
@@ -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;
index 9e7e5328082a94541deb9c982d2266b76976e32d..acab7e2425b24bcefb9a3bbf2e5487783c79af04 100644 (file)
@@ -20,7 +20,7 @@
 
 //version definition 
 #define VERSION "0.3"
-#define RELEASE "20"
+#define RELEASE "21"
 
 //Public variables
 PUBLIC  int debug=0;            //debug level
index 7efcd65e7c8c974f35c35f70e895f8023d6d23a1..68a94a8009e19dec8e3ca0435811bca67ab530cd 100644 (file)
@@ -10,6 +10,7 @@
 #include        <linux/types.h>
 #include        <stdbool.h>
 #include       <stdarg.h>
+#include        <time.h>
 
 
 #define APPNAME "maild"         //application name
diff --git a/lib/unissl.c b/lib/unissl.c
new file mode 100644 (file)
index 0000000..ae802bc
--- /dev/null
@@ -0,0 +1,55 @@
+// vim: smarttab tabstop=8 shiftwidth=2 expandtab
+/********************************************************/
+/*                                                     */
+/*     Implement all routine to manage SMTP low level  */
+/*     exchange.                                       */
+/*                                                     */
+/********************************************************/
+#include        <openssl/err.h>
+#include        <openssl/ssl.h>
+#include        <stdbool.h>
+#include        <stdio.h>
+
+#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 (file)
index 0000000..ef8d25b
--- /dev/null
@@ -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