/* tls.c - MessageWall TLS definitions Copyright (C) 2002 Ian Gulliver This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. 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 */ #include #include #include #include "messagewall.h" #include "tls.h" static const char tagstring[] = "$Id: tls.c,v 1.17 2002/07/11 03:10:38 ian Exp $"; #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif void tls_client_error(int client) { char debug[1024]; fprintf(stderr,"{%d} (%d) TLS/FATAL: %s\n",process,client,ERR_error_string(ERR_get_error(),debug)); } void tls_backend_error(int backend) { char debug[1024]; fprintf(stderr,"{%d} [%d] TLS/FATAL: %s\n",process,backend,ERR_error_string(ERR_get_error(),debug)); } int tls_start(int client) { clients[client].ssl = SSL_new(client_ctx); if (clients[client].ssl == NULL) { tls_client_error(client); return 1; } if (SSL_set_fd(clients[client].ssl,clients[client].fd) != 1) { tls_client_error(client); return 1; } clients[client].ssl_handshake = 1; return 0; } int tls_handshake(int client) { int i; i = SSL_accept(clients[client].ssl); if (i == 1) { /* * successfully now speaking SSL */ fprintf(stderr,"{%d} (%d) TLS/SUCCESS: now speaking TLS\n",process,client); clients[client].ssl_handshake = 0; return 0; } if (i == 0) { /* * successfully now *not* speaking SSL */ fprintf(stderr,"{%d} (%d) TLS/STATUS: agreed not to speak TLS\n",process,client); tls_client_error(client); clients[client].ssl_handshake = 0; clients[client].ssl = NULL; return 0; } if (i < 0) { i = SSL_get_error(clients[client].ssl,i); if (i == SSL_ERROR_WANT_READ || i == SSL_ERROR_WANT_WRITE) return -1; tls_client_error(client); return 1; } return 1; } int tls_client_start(int backend) { int i; /* * set up SSL object for client */ backends[backend].ssl = SSL_new(backend_ctx); if (backends[backend].ssl == NULL) { tls_backend_error(backend); return 1; } if (SSL_set_fd(backends[backend].ssl,backends[backend].fd) != 1) { tls_backend_error(backend); return 1; } i = SSL_connect(backends[backend].ssl); if (i == 1) { fprintf(stderr,"{%d} [%d] TLS/SUCCESS: now speaking TLS\n",process,backend); return 2; } if (i == 0) { tls_backend_error(backend); return 1; } return 0; } int tls_client_handshake(int backend) { int i; i = SSL_connect(backends[backend].ssl); if (i == 1) { /* * successfully now speaking SSL */ fprintf(stderr,"{%d} [%d] TLS/SUCCESS: now speaking TLS\n",process,backend); return 0; } if (i == 0) { /* * successfully now *not* speaking SSL */ fprintf(stderr,"{%d} [%d] TLS/STATUS: agreed not to speak TLS\n",process,backend); tls_backend_error(backend); backends[backend].ssl = NULL; return 0; } if (i < 0) { i = SSL_get_error(backends[backend].ssl,i); if (i == SSL_ERROR_WANT_READ || i == SSL_ERROR_WANT_WRITE) return -1; tls_backend_error(backend); return 1; } return 1; } int tls_client_write(int client, char *buf, int len) { if (clients[client].ssl == NULL || clients[client].ssl_handshake == 1) return write(clients[client].fd,buf,len); else return SSL_write(clients[client].ssl,buf,len); } int tls_client_read(int client, char *buf, int len) { if (clients[client].ssl == NULL || clients[client].ssl_handshake == 1) return read(clients[client].fd,buf,len); else return SSL_read(clients[client].ssl,buf,len); } int tls_backend_write(int backend, char *buf, int len) { if (backends[backend].ssl == NULL) return send(backends[backend].fd,buf,len,MSG_NOSIGNAL); else return SSL_write(backends[backend].ssl,buf,len); } int tls_backend_read(int backend, char *buf, int len) { if (backends[backend].ssl == NULL) return read(backends[backend].fd,buf,len); else return SSL_read(backends[backend].ssl,buf,len); } int tls_client_eread(int client, struct firestring_estr_t *f) { int i; if (f->l == f->a) return 2; i = tls_client_read(client,&f->s[f->l],f->a - f->l); if (i < 0) return 0; if (i == 0) return 1; f->l += i; return 0; } int tls_backend_eread(int backend, struct firestring_estr_t *f) { int i; if (f->l == f->a) return 2; i = tls_backend_read(backend,&f->s[f->l],f->a - f->l); if (i < 0) return 0; if (i == 0) return 1; f->l += i; return 0; }