/*************************************************************************/ /* sslc.c */ /* v. 0.1 */ /* Copyright (C) 2008 Paolo Ardoino, */ /* by Paolo Ardoino < paolo.ardoino@gmail.com > */ /* */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License as */ /* published by the Free Software Foundation; either version 2 of the */ /* License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, but */ /* WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- */ /* 1307, USA. */ /*************************************************************************/ #ifndef SSLC_H #define SSLC_H #include #define MAX_THREADS 100 #define BUFFER_SIZE 512 #define READ_BUFFER(ssl, buf) do { SSL_read((SSL *) ssl, (buf), BUFFER_SIZE); (buf)[strlen(buf) - 2] = '\0'; } while(0) #define WRITE_BUFFER(ssl, buf) do { SSL_write((SSL *) ssl, (buf), strlen(buf)); } while(0) static void ssl_thread_setup(void); static void ssl_thread_cleanup(void); static void locking_function(int mode, int type, const char *file, int line); static unsigned long id_function(void); static void *open_sslc(struct hostent *hent, int port, char *user, char *password); static void close_sslc(void *ssl); #endif /* SSLC_H */ #include #include #include #include #include #include #include #include #include #include #include #include #include static pthread_mutex_t *lock_cs; static long *lock_count; static pthread_mutex_t locker = PTHREAD_MUTEX_INITIALIZER; static int mtctr; static unsigned long id_function(void) { return ((unsigned long) pthread_self()); } static void locking_function(int mode, int type, const char *file, int line) { if (mode & CRYPTO_LOCK) { pthread_mutex_lock(&lock_cs[type]); lock_count[type]++; } else { pthread_mutex_unlock(&lock_cs[type]); } } static void ssl_thread_setup(void) { int num = CRYPTO_num_locks(); int ctr; lock_cs = (pthread_mutex_t*) OPENSSL_malloc(num * sizeof(pthread_mutex_t)); lock_count = (long*) OPENSSL_malloc(num * sizeof(long)); for (ctr = 0; ctr < num; ctr++) { lock_count[ctr] = 0; pthread_mutex_init(&lock_cs[ctr], NULL); } CRYPTO_set_id_callback(id_function); CRYPTO_set_locking_callback(locking_function); } static void ssl_thread_cleanup(void) { int ctr; CRYPTO_set_locking_callback(NULL); for (ctr = 0; ctr < CRYPTO_num_locks(); ctr++) { pthread_mutex_destroy(&lock_cs[ctr]); } OPENSSL_free(lock_cs); OPENSSL_free(lock_count); } static void *open_sslc(struct hostent *hent, int port, char *user, char *password) { struct sockaddr_in sa; int sd; char cmd[BUFFER_SIZE]; SSL *ssl; SSL_CTX *ctx; pthread_mutex_lock(&locker); if (!mtctr++) { ssl_thread_setup(); } pthread_mutex_unlock(&locker); sa.sin_family = hent->h_addrtype; sa.sin_port = htons(port); memcpy((char *) &sa.sin_addr.s_addr, hent->h_addr_list[0], hent->h_length); if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { printf("cannot open socket for '%s'\n", hent->h_name); return NULL; } printf("connecting to '%s'\n", hent->h_name); if (connect(sd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) == -1) { printf("connection failed on '%s'\n", hent->h_name); close(sd); return NULL; } printf("'%s' connected\n", hent->h_name); SSLeay_add_ssl_algorithms(); ctx = SSL_CTX_new(SSLv23_client_method()); ssl = SSL_new(ctx); SSL_CTX_free(ctx); SSL_set_fd(ssl,sd); if (SSL_connect(ssl) == 1) { return ssl; } printf("cannot authenticate on '%s'\n", hent->h_name); if (!SSL_shutdown(ssl)) { SSL_shutdown(ssl); } close(sd); SSL_free(ssl); pthread_mutex_lock(&locker); if (!--mtctr) { ssl_thread_cleanup(); } pthread_mutex_unlock(&locker); return NULL; } static void close_sslc(void *ssl) { char cmd[BUFFER_SIZE]; sprintf(cmd, "QUIT\r\n"); WRITE_BUFFER(ssl,cmd); READ_BUFFER(ssl,cmd); if (ERR_BUFFER(cmd)) { printf("sslc refuses to quit\n"); } if (!SSL_shutdown(ssl)) { SSL_shutdown(ssl); } close(SSL_get_fd(ssl)); SSL_free(ssl); pthread_mutex_lock(&locker); if (!--mtctr) { ssl_thread_cleanup(); } pthread_mutex_unlock(&locker); }