summaryrefslogtreecommitdiff
path: root/vchat-ssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'vchat-ssl.c')
-rwxr-xr-xvchat-ssl.c108
1 files changed, 92 insertions, 16 deletions
diff --git a/vchat-ssl.c b/vchat-ssl.c
index 7060e29..79092a6 100755
--- a/vchat-ssl.c
+++ b/vchat-ssl.c
@@ -32,7 +32,7 @@
32#include "vchat.h" 32#include "vchat.h"
33#include "vchat-ssl.h" 33#include "vchat-ssl.h"
34 34
35char *vchat_ssl_version = "$Id$"; 35const char *vchat_ssl_version = "vchat-ssl.c $Id$";
36 36
37#define VC_CTX_ERR_EXIT(se, cx) do { \ 37#define VC_CTX_ERR_EXIT(se, cx) do { \
38 snprintf(tmpstr, TMPSTRSIZE, "CREATE CTX: %s", \ 38 snprintf(tmpstr, TMPSTRSIZE, "CREATE CTX: %s", \
@@ -61,6 +61,7 @@ SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store )
61 X509_STORE *store = NULL; 61 X509_STORE *store = NULL;
62 vc_x509verify_cb_t verify_callback = NULL; 62 vc_x509verify_cb_t verify_callback = NULL;
63 63
64 /* Explicitly use TLSv1 (or maybe later) */
64 if( !(ctx = SSL_CTX_new(SSLv23_client_method())) ) 65 if( !(ctx = SSL_CTX_new(SSLv23_client_method())) )
65 VC_CTX_ERR_EXIT(store, ctx); 66 VC_CTX_ERR_EXIT(store, ctx);
66 67
@@ -69,13 +70,16 @@ SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store )
69 70
70 SSL_CTX_set_cert_store(ctx, store); 71 SSL_CTX_set_cert_store(ctx, store);
71 store = NULL; 72 store = NULL;
73 /* Disable some insecure protocols explicitly */
72 SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); 74 SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
73 if( OPENSSL_VERSION_NUMBER < 0x10000000L ) 75 if (getstroption(CF_CIPHERSUITE))
76 SSL_CTX_set_cipher_list(ctx, getstroption(CF_CIPHERSUITE));
77 else if( OPENSSL_VERSION_NUMBER < 0x10000000L )
74 SSL_CTX_set_cipher_list(ctx, "DHE-RSA-AES256-SHA"); 78 SSL_CTX_set_cipher_list(ctx, "DHE-RSA-AES256-SHA");
75 else 79 else
76 SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES256-GCM-SHA384"); 80 SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES256-GCM-SHA384");
77 81
78 SSL_CTX_set_verify_depth (ctx, 2); 82 SSL_CTX_set_verify_depth (ctx, getintoption(CF_VERIFYSSL));
79 83
80 if( !(verify_callback = vc_store->callback) ) 84 if( !(verify_callback = vc_store->callback) )
81 verify_callback = vc_verify_callback; 85 verify_callback = vc_verify_callback;
@@ -137,6 +141,7 @@ int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store )
137 BIO_push( ssl_conn, *conn ); 141 BIO_push( ssl_conn, *conn );
138 *conn = ssl_conn; 142 *conn = ssl_conn;
139 fflush(stdout); 143 fflush(stdout);
144
140 if( BIO_do_handshake( *conn ) > 0 ) { 145 if( BIO_do_handshake( *conn ) > 0 ) {
141 /* Show information about cipher used */ 146 /* Show information about cipher used */
142 const SSL *sslp = NULL; 147 const SSL *sslp = NULL;
@@ -144,20 +149,89 @@ int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store )
144 149
145 /* Get cipher object */ 150 /* Get cipher object */
146 BIO_get_ssl(ssl_conn, &sslp); 151 BIO_get_ssl(ssl_conn, &sslp);
152 if (sslp)
147 cipher = SSL_get_current_cipher(sslp); 153 cipher = SSL_get_current_cipher(sslp);
148 if (cipher) { 154 if (cipher) {
149 char cipher_desc[TMPSTRSIZE]; 155 char cipher_desc[TMPSTRSIZE];
150 snprintf(tmpstr, TMPSTRSIZE, "[SSL CIPHER] %s", SSL_CIPHER_description(cipher, cipher_desc, TMPSTRSIZE)); 156 snprintf(tmpstr, TMPSTRSIZE, "[SSL CIPHER ] %s", SSL_CIPHER_description(cipher, cipher_desc, TMPSTRSIZE));
151 writecf(FS_SERV, tmpstr); 157 writecf(FS_SERV, tmpstr);
152 } else { 158 } else {
153 snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR] Cipher not known / SSL object can't be queried!"); 159 snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR ] Cipher not known / SSL object can't be queried!");
154 writecf(FS_ERR, tmpstr); 160 writecf(FS_ERR, tmpstr);
155 } 161 }
156 return 0; 162
163 /* Accept being connected, _if_ verification passed */
164 if (sslp) {
165 long result = SSL_get_verify_result(sslp);
166
167 /* show & verify fingerprint */
168 if (result == X509_V_OK) {
169 X509 *peercert = SSL_get_peer_certificate(sslp);
170
171 /* FIXME: this IS bad code */
172 char new_fingerprint[TMPSTRSIZE] = "";
173 char old_fingerprint[TMPSTRSIZE] = "";
174 FILE *fingerprint_file = NULL;
175
176 unsigned int fingerprint_len;
177 unsigned char fingerprint_bin[EVP_MAX_MD_SIZE];
178
179 /* show basic information about peer cert */
180 snprintf(tmpstr, TMPSTRSIZE, "[SSL SUBJECT ] %s", X509_NAME_oneline(X509_get_subject_name(peercert),0,0));
181 writecf(FS_SERV, tmpstr);
182 snprintf(tmpstr, TMPSTRSIZE, "[SSL ISSUER ] %s", X509_NAME_oneline(X509_get_issuer_name(peercert),0,0));
183 writecf(FS_SERV, tmpstr);
184
185 /* calculate fingerprint */
186 if (X509_digest(peercert,EVP_sha1(),fingerprint_bin,&fingerprint_len)) {
187 char shorttmpstr[3] = "XX";
188 int j;
189 for (j=0; j<(int)fingerprint_len; j++) {
190 if (j)
191 strncat(new_fingerprint, ":", TMPSTRSIZE);
192 snprintf(shorttmpstr, 3, "%02X", fingerprint_bin[j]);
193 strncat(new_fingerprint, shorttmpstr, TMPSTRSIZE);
194 }
195 snprintf(tmpstr, TMPSTRSIZE, "[SSL FINGERPRINT ] from server: %s", new_fingerprint);
196 writecf(FS_SERV, tmpstr);
197 }
198
199 // we don't need the peercert anymore
200 X509_free(peercert);
201
202 fingerprint_file = fopen(tilde_expand(getstroption(CF_FINGERPRINT)), "r");
203 if (fingerprint_file) {
204 fgets(old_fingerprint, TMPSTRSIZE, fingerprint_file);
205 fclose(fingerprint_file);
206
207 /* verify fingerprint matches stored version */
208 if (!strncmp(new_fingerprint, old_fingerprint, TMPSTRSIZE))
209 return 0;
210 else {
211 snprintf(tmpstr, TMPSTRSIZE, "[SSL FINGERPRINT ] from %s: %s", getstroption(CF_FINGERPRINT), old_fingerprint);
212 writecf(FS_ERR, tmpstr);
213 writecf(FS_ERR, "[SSL CONNECT ERROR] Fingerprint mismatch! Server cert updated?");
214 return 1;
215 }
216 } else {
217 /* FIXME: there might be other errors than missing file */
218 fingerprint_file = fopen(tilde_expand(getstroption(CF_FINGERPRINT)), "w");
219 if (!fingerprint_file) {
220 snprintf (tmpstr, TMPSTRSIZE, "Can't write fingerprint file, %s.", strerror(errno));
221 writecf(FS_ERR, tmpstr);
222 } else {
223 fputs(new_fingerprint, fingerprint_file);
224 fclose(fingerprint_file);
225 writecf(FS_SERV, "Stored fingerprint.");
226 return 0;
227 }
228 }
229 }
230 }
157 } 231 }
158 } 232 }
159 233
160 snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR] %s", ERR_error_string (ERR_get_error (), NULL)); 234 snprintf(tmpstr, TMPSTRSIZE, "[SSL CONNECT ERROR] %s", ERR_error_string (ERR_get_error (), NULL));
161 writecf(FS_ERR, tmpstr); 235 writecf(FS_ERR, tmpstr);
162 236
163 return 1; 237 return 1;
@@ -227,17 +301,11 @@ X509_STORE *vc_x509store_create(vc_x509store_t *vc_store)
227int vc_verify_callback(int ok, X509_STORE_CTX *store) 301int vc_verify_callback(int ok, X509_STORE_CTX *store)
228{ 302{
229 if(!ok) { 303 if(!ok) {
230 /* XXX handle action/abort */ 304 snprintf(tmpstr, TMPSTRSIZE, "[SSL VERIFY ERROR ] %s",
231 if(!(ok=getintoption(CF_IGNSSL)))
232 snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR] %s",
233 X509_verify_cert_error_string(store->error));
234 else
235 snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR] %s (ignored)",
236 X509_verify_cert_error_string(store->error)); 305 X509_verify_cert_error_string(store->error));
237
238 writecf(FS_ERR, tmpstr); 306 writecf(FS_ERR, tmpstr);
239 } 307 }
240 return(ok); 308 return ok;
241} 309}
242 310
243void vc_x509store_setflags(vc_x509store_t *store, int flags) 311void vc_x509store_setflags(vc_x509store_t *store, int flags)
@@ -323,6 +391,14 @@ void vc_cleanup_x509store(vc_x509store_t *s)
323 free(s->use_keyfile); 391 free(s->use_keyfile);
324 free(s->use_key); 392 free(s->use_key);
325 sk_X509_free(s->certs); 393 sk_X509_free(s->certs);
326 sk_X509_free(s->crls); 394 sk_X509_CRL_free(s->crls);
327 sk_X509_free(s->use_certs); 395 sk_X509_free(s->use_certs);
328} 396}
397
398const char *vchat_ssl_version_external = "OpenSSL implementation; version unknown";
399void vchat_ssl_get_version_external()
400{
401 char tmpstr[TMPSTRSIZE];
402 snprintf(tmpstr, TMPSTRSIZE, "%s with %s", SSLeay_version(SSLEAY_VERSION), SSLeay_version(SSLEAY_CFLAGS));
403 vchat_ssl_version_external = strdup(tmpstr);
404}