diff options
| author | erdgeist <de@gsmk.de> | 2014-04-16 20:12:34 +0200 |
|---|---|---|
| committer | erdgeist <de@gsmk.de> | 2014-04-16 20:12:34 +0200 |
| commit | b32861fa6ec00c655b7a43ab0d511c7048f1ee43 (patch) | |
| tree | 50cd33c87b43ff5c9a7a029346386cef2bdff5c6 /vchat-ssl.c | |
| parent | 71fb4ac25542721f3a2d42ac4eef0d7296968f82 (diff) | |
| parent | 3297473435ad53b6691d6c772f83457a72134c48 (diff) | |
Merge from github
Diffstat (limited to 'vchat-ssl.c')
| -rwxr-xr-x | vchat-ssl.c | 108 |
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 | ||
| 35 | char *vchat_ssl_version = "$Id$"; | 35 | const 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) | |||
| 227 | int vc_verify_callback(int ok, X509_STORE_CTX *store) | 301 | int 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 | ||
| 243 | void vc_x509store_setflags(vc_x509store_t *store, int flags) | 311 | void 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 | |||
| 398 | const char *vchat_ssl_version_external = "OpenSSL implementation; version unknown"; | ||
| 399 | void 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 | } | ||
