Read This! | Picolisp | Picolisp Machine | Pil Sources | Pil Tutorials | Linux | BASH | C-Programmming | Javascipt | Python | Scheme | Operating Systems | AssemblyLanguage | Computer Security | Firewalls | Exploitation | Social Engineering | Metasploit | Emacs | vim | Pharo Smalltalk | Databases | Networking | Machine Learning | Git | Machine Learning | Algorithms | Open Data Science

ssl.c


/* 28mar17abu
 * (c) Software Lab. Alexander Burger
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/stat.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>

#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

typedef enum {NO,YES} bool;

static char *File, *Dir, *Data;
static off_t Size;
static bool Safe, Hot;

static char Ciphers[] = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:DES-CBC3-SHA";

static char Get[] =
   "GET /%s HTTP/1.0rn"
   "User-Agent: PicoLisprn"
   "Host: %s:%srn"
   "Accept-Charset: utf-8rnrn";

static void giveup(char *msg) {
   fprintf(stderr, "ssl: %sn", msg);
   exit(1);
}

static int sslConnect(SSL *ssl, char *node, char *service) {
   struct addrinfo hints, *lst, *p;
   int sd;

   memset(&hints, 0, sizeof(hints));
   hints.ai_family = AF_UNSPEC;
   hints.ai_socktype = SOCK_STREAM;
   if (getaddrinfo(node, service, &hints, &lst) == 0) {
      for (p = lst; p; p = p->ai_next) {
         if ((sd = socket(p->ai_family, p->ai_socktype, 0)) >= 0) {
            if (connect(sd, p->ai_addr, p->ai_addrlen) == 0) {
               SSL_set_fd(ssl, sd);
               if (SSL_connect(ssl) == 1) {
                  X509 *cert;

                  freeaddrinfo(lst);
                  if (Safe)
                     return sd;
                  if (cert = SSL_get_peer_certificate(ssl)) {
                     X509_free(cert);
                     if (SSL_get_verify_result(ssl) == X509_V_OK)
                        return sd;
                  }
                  return -1;
               }
            }
            close(sd);
         }
      }
      freeaddrinfo(lst);
   }
   return -1;
}

static void sslClose(SSL *ssl, int sd) {
   SSL_shutdown(ssl);
   SSL_clear(ssl);
   close(sd);
}

static bool sslFile(SSL *ssl, char *file) {
   int fd, n;
   char buf[BUFSIZ];

   if (file[0] == '-') {
      if (file[1] != '0')
         return SSL_write(ssl, file+1, strlen(file)-1) >= 0;
      fd = STDIN_FILENO;
   }
   else if ((fd = open(file, O_RDONLY)) < 0)
      return NO;
   while ((n = read(fd, buf, sizeof(buf))) > 0)
      if (SSL_write(ssl, buf, n) < 0) {
         close(fd);
         return NO;
      }
   close(fd);
   return n == 0;
}

static void lockFile(int fd) {
   struct flock fl;

   fl.l_type = F_WRLCK;
   fl.l_whence = SEEK_SET;
   fl.l_start = 0;
   fl.l_len = 0;
   if (fcntl(fd, F_SETLKW, &fl) < 0)
      giveup("Can't lock");
}

static void doSigTerm(int n __attribute__((unused))) {
   int fd;
   struct stat st;
   char *data;

   if (Hot) {
      if ((fd = open(File, O_RDWR)) < 0)
         giveup("Can't final open");
      lockFile(fd);
      if (fstat(fd,&st) < 0)
         giveup("Can't final access");
      if (st.st_size != 0) {
         if ((data = malloc(st.st_size)) == NULL)
            giveup("Can't final alloc");
         if (read(fd, data, st.st_size) != st.st_size)
            giveup("Can't final read");
         if (ftruncate(fd,0) < 0)
            giveup("Can't final truncate");
      }
      if (write(fd, Data, Size) != Size)
         giveup("Can't final write (1)");
      if (st.st_size != 0  &&  write(fd, data, st.st_size) != st.st_size)
         giveup("Can't final write (2)");
   }
   exit(0);
}

static void iSignal(int n, void (*foo)(int)) {
   struct sigaction act;

   act.sa_handler = foo;
   sigemptyset(&act.sa_mask);
   act.sa_flags = 0;
   sigaction(n, &act, NULL);
}

// ssl host port url
// ssl host port url [key [file]]
// ssl host port url key file dir sec [min]
int main(int ac, char *av[]) {
   bool dbg;
   SSL_CTX *ctx;
   SSL *ssl;
   int n, sec, lim, getLen, lenLen, fd, sd;
   DIR *dp;
   struct dirent *p;
   struct stat st;
   char get[1024], buf[4096], nm[4096], len[64];

   if (dbg = strcmp(av[ac-1], "+") == 0)
      --ac;
   if (!(ac >= 4 && ac <= 6  ||  ac >= 8 && ac <= 9))
      giveup("host port url [[key] file] | host port url key file dir sec [min]");
   if (*av[2] == '-')
      ++av[2],  Safe = YES;
   if (strlen(Get)+strlen(av[1])+strlen(av[2])+strlen(av[3]) >= sizeof(get))
      giveup("Names too long");
   getLen = sprintf(get, Get, av[3], av[1], av[2]);

   SSL_library_init();
   SSL_load_error_strings();
   if (!(ctx = SSL_CTX_new(SSLv23_client_method())) || !SSL_CTX_set_default_verify_paths(ctx)) {
      ERR_print_errors_fp(stderr);
      giveup("SSL init");
   }
   SSL_CTX_set_options(ctx,
      SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_ALL | SSL_OP_NO_COMPRESSION );
   SSL_CTX_set_cipher_list(ctx, Ciphers);
   ssl = SSL_new(ctx);

   if (ac <= 6) {
      if (sslConnect(ssl, av[1], av[2]) < 0) {
         ERR_print_errors_fp(stderr);
         giveup("Can't connect");
      }
      if (SSL_write(ssl, get, getLen) < 0) {
         ERR_print_errors_fp(stderr);
         giveup("SSL GET");
      }
      if (ac > 4) {
         if (*av[4]  &&  !sslFile(ssl,av[4]))
            giveup(av[4]);
         if (ac > 5  &&  *av[5]  &&  !sslFile(ssl,av[5]))
            giveup(av[5]);
      }
      while ((n = SSL_read(ssl, buf, sizeof(buf))) > 0)
         write(STDOUT_FILENO, buf, n);
      if (dbg)
         ERR_print_errors_fp(stderr);
      return 0;
   }
   if (!dbg) {
      signal(SIGCHLD,SIG_IGN);  /* Prevent zombies */
      if ((n = fork()) < 0)
         giveup("detach");
      if (n)
         return 0;
      setsid();
   }
   File = av[5];
   Dir = av[6];
   sec = atoi(av[7]);
   iSignal(SIGINT, doSigTerm);
   iSignal(SIGTERM, doSigTerm);
   signal(SIGPIPE, SIG_IGN);
   lim = 0;
   if (ac > 8) {
      iSignal(SIGALRM, doSigTerm);
      alarm(lim = 60 * atoi(av[8]));
   }
   for (;;) {
      if (*File && (fd = open(File, O_RDWR)) >= 0) {
         if (fstat(fd,&st) < 0  ||  st.st_size == 0)
            close(fd);
         else {
            alarm(lim);
            lockFile(fd);
            if (fstat(fd,&st) < 0  ||  (Size = st.st_size) == 0)
               giveup("Can't access");
            lenLen = sprintf(len, "%ldn", Size);
            if ((Data = malloc(Size)) == NULL)
               giveup("Can't alloc");
            if (read(fd, Data, Size) != Size)
               giveup("Can't read");
            Hot = YES;
            if (ftruncate(fd,0) < 0)
               giveup("Can't truncate");
            close(fd);
            for (;;) {
               if ((sd = sslConnect(ssl, av[1], av[2])) >= 0) {
                  if (SSL_write(ssl, get, getLen) == getLen  &&
                        (!*av[4] || sslFile(ssl,av[4]))  &&       // key
                        SSL_write(ssl, len, lenLen) == lenLen  && // length
                        SSL_write(ssl, Data, Size) == Size  &&    // data
                        SSL_write(ssl, "T", 1) == 1  &&           // ack
                        SSL_read(ssl, buf, 1) == 1  &&  buf[0] == 'T' ) {
                     Hot = NO;
                     sslClose(ssl,sd);
                     break;
                  }
                  sslClose(ssl,sd);
               }
               if (dbg)
                  ERR_print_errors_fp(stderr);
               sleep(sec);
            }
            free(Data);
         }
      }
      if (*Dir && (dp = opendir(Dir))) {
         while (p = readdir(dp)) {
            if (p->d_name[0] == '=') {
               snprintf(nm, sizeof(nm), "%s%s", Dir, p->d_name);
               if ((n = readlink(nm, buf, sizeof(buf))) > 0  &&  stat(nm, &st) >= 0) {
                  lenLen = sprintf(len, "%ldn", st.st_size);
                  buf[n++] = 'n';
                  alarm(lim);
                  if ((sd = sslConnect(ssl, av[1], av[2])) >= 0) {
                     if (SSL_write(ssl, get, getLen) == getLen  &&
                           (!*av[4] || sslFile(ssl,av[4]))  &&       // key
                           SSL_write(ssl, buf, n) == n  &&           // path
                           SSL_write(ssl, len, lenLen) == lenLen  && // length
                           sslFile(ssl, nm)  &&                      // file
                           SSL_write(ssl, "T", 1) == 1  &&           // ack
                           SSL_read(ssl, buf, 1) == 1  &&  buf[0] == 'T' )
                        unlink(nm);
                     sslClose(ssl,sd);
                  }
                  if (dbg)
                     ERR_print_errors_fp(stderr);
               }
            }
         }
         closedir(dp);
      }
      sleep(sec);
   }
}


http:///wiki/?sslc

29jun17   admin