5 #include <openssl/ssl.h>
6 #include <openssl/err.h>
7 #include <openssl/rand.h>
13 #include <sys/types.h>
15 #include "client_crypto.h"
20 int ssl_is_connected = 0;
21 #ifdef THREADED_CLIENT
22 pthread_mutex_t **Critters; /* Things that need locking */
23 #endif /* THREADED_CLIENT */
26 extern int server_is_local;
27 #endif /* HAVE_OPENSSL */
32 * input binary data from encrypted connection
34 void serv_read_ssl(char *buf, int bytes)
41 if (SSL_want_read(ssl)) {
42 if ((SSL_write(ssl, junk, 0)) < 1) {
43 fprintf(stderr, "SSL_write in serv_read:\n");
44 ERR_print_errors_fp(stderr);
47 rlen = SSL_read(ssl, &buf[len], bytes - len);
51 errval = SSL_get_error(ssl, rlen);
52 if (errval == SSL_ERROR_WANT_READ ||
53 errval == SSL_ERROR_WANT_WRITE) {
57 if (errval == SSL_ERROR_ZERO_RETURN ||
58 errval == SSL_ERROR_SSL) {
60 serv_read(&buf[len], bytes - len);
63 fprintf(stderr, "SSL_read in serv_read:\n");
64 ERR_print_errors_fp(stderr);
74 * send binary to server encrypted
76 void serv_write_ssl(char *buf, int nbytes)
78 int bytes_written = 0;
82 while (bytes_written < nbytes) {
83 if (SSL_want_write(ssl)) {
84 if ((SSL_read(ssl, junk, 0)) < 1) {
85 fprintf(stderr, "SSL_read in serv_write:\n");
86 ERR_print_errors_fp(stderr);
89 retval = SSL_write(ssl, &buf[bytes_written],
90 nbytes - bytes_written);
94 errval = SSL_get_error(ssl, retval);
95 if (errval == SSL_ERROR_WANT_READ ||
96 errval == SSL_ERROR_WANT_WRITE) {
100 if (errval == SSL_ERROR_ZERO_RETURN ||
101 errval == SSL_ERROR_SSL) {
103 serv_write(&buf[bytes_written],
104 nbytes - bytes_written);
107 fprintf(stderr, "SSL_write in serv_write:\n");
108 ERR_print_errors_fp(stderr);
112 bytes_written += retval;
117 void ssl_lock(int mode, int n, const char *file, int line)
119 #ifdef THREADED_CLIENT
120 if (mode & CRYPTO_LOCK)
121 pthread_mutex_lock(Critters[n]);
123 pthread_mutex_unlock(Critters[n]);
124 #endif /* THREADED_CLIENT */
126 #endif /* HAVE_OPENSSL */
130 * starttls() starts SSL/TLS if possible
131 * Returns 1 if the session is encrypted, 0 otherwise
138 SSL_METHOD *ssl_method;
141 /* TLS is pointless when server is local */
142 if (server_is_local) {
150 SSL_load_error_strings();
151 SSLeay_add_ssl_algorithms();
153 /* Set up the SSL context in which we will oeprate */
154 ssl_method = SSLv23_client_method();
155 ssl_ctx = SSL_CTX_new(ssl_method);
157 fprintf(stderr, "SSL_CTX_new failed: %s\n",
158 ERR_reason_error_string(ERR_get_error()));
161 /* Any reasonable cipher we can get */
162 if (!(SSL_CTX_set_cipher_list(ssl_ctx, CIT_CIPHERS))) {
163 fprintf(stderr, "No ciphers available for encryption\n");
164 SSL_CTX_free(ssl_ctx);
168 SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_BOTH);
170 /* Load DH parameters into the context */
173 fprintf(stderr, "Can't allocate a DH object: %s\n",
174 ERR_reason_error_string(ERR_get_error()));
177 if (!(BN_hex2bn(&(dh->p), DH_P))) {
178 fprintf(stderr, "Can't assign DH_P: %s\n",
179 ERR_reason_error_string(ERR_get_error()));
182 if (!(BN_hex2bn(&(dh->g), DH_G))) {
183 fprintf(stderr, "Can't assign DH_G: %s\n",
184 ERR_reason_error_string(ERR_get_error()));
188 SSL_CTX_set_tmp_dh(ssl_ctx, dh);
191 #ifdef THREADED_CLIENT
192 /* OpenSSL requires callbacks for threaded clients */
193 CRYPTO_set_locking_callback(ssl_lock);
194 CRYPTO_set_id_callback(pthread_self);
196 /* OpenSSL requires us to do semaphores for threaded clients */
197 Critters = malloc(CRYPTO_num_locks() * sizeof (pthread_mutex_t *));
199 perror("malloc failed");
202 for (a = 0; a < CRYPTO_num_locks(); a++) {
203 Critters[a] = malloc(sizeof (pthread_mutex_t));
205 perror("malloc failed");
208 pthread_mutex_init(Critters[a], NULL);
211 #endif /* THREADED_CLIENT */
214 ssl = SSL_new(ssl_ctx);
216 fprintf(stderr, "SSL_new failed: %s\n",
217 ERR_reason_error_string(ERR_get_error()));
218 SSL_CTX_free(ssl_ctx);
222 /* Pointless flag waving */
223 #if SSLEAY_VERSION_NUMBER >= 0x0922
224 SSL_set_session_id_context(ssl, "Citadel/UX SID", 14);
226 if (!RAND_status()) {
227 fprintf(stderr, "PRNG not properly seeded\n");
231 /* Associate network connection with SSL object */
232 if (SSL_set_fd(ssl, serv_sock) < 1) {
233 fprintf(stderr, "SSL_set_fd failed: %s\n",
234 ERR_reason_error_string(ERR_get_error()));
235 SSL_CTX_free(ssl_ctx);
242 printf("Requesting encryption...\r");
245 /* Ready to start SSL/TLS */
249 fprintf(stderr, "Server can't start TLS: %s\n", &buf[4]);
253 /* Do SSL/TLS handshake */
254 if ((a = SSL_connect(ssl)) < 1) {
255 fprintf(stderr, "SSL_connect failed: %s\n",
256 ERR_reason_error_string(ERR_get_error()));
257 SSL_CTX_free(ssl_ctx);
263 BIO_set_close(ssl->rbio, BIO_NOCLOSE);
267 bits = SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), &alg_bits);
268 printf("Encrypting with %s cipher %s (%d of %d bits)\n",
269 SSL_CIPHER_get_version(SSL_get_current_cipher(ssl)),
270 SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)),
273 ssl_is_connected = 1;
277 #endif /* HAVE_OPENSSL */
282 * void endtls() - end SSL/TLS session
292 ssl_is_connected = 0;
294 SSL_CTX_free(ssl_ctx);