diff options
Diffstat (limited to 'vchat-tls.c')
| -rwxr-xr-x | vchat-tls.c | 481 |
1 files changed, 481 insertions, 0 deletions
diff --git a/vchat-tls.c b/vchat-tls.c new file mode 100755 index 0000000..a6e5e2d --- /dev/null +++ b/vchat-tls.c | |||
| @@ -0,0 +1,481 @@ | |||
| 1 | /* | ||
| 2 | * vchat-client - alpha version | ||
| 3 | * vchat-tls.c - handling of SSL connection and X509 certificate | ||
| 4 | * verification | ||
| 5 | * | ||
| 6 | * Copyright (C) 2007 Thorsten Schroeder <ths@berlin.ccc.de> | ||
| 7 | * | ||
| 8 | * This program is free software. It can be redistributed and/or modified, | ||
| 9 | * provided that this copyright notice is kept intact. This program is | ||
| 10 | * distributed in the hope that it will be useful, but without any warranty; | ||
| 11 | * without even the implied warranty of merchantability or fitness for a | ||
| 12 | * particular purpose. In no event shall the copyright holder be liable for | ||
| 13 | * any direct, indirect, incidental or special damages arising in any way out | ||
| 14 | * of the use of this software. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <stdio.h> | ||
| 19 | #include <stdlib.h> | ||
| 20 | #include <string.h> | ||
| 21 | #include <assert.h> | ||
| 22 | |||
| 23 | #include <openssl/err.h> | ||
| 24 | #include <openssl/ssl.h> | ||
| 25 | #include <openssl/bio.h> | ||
| 26 | #include <openssl/evp.h> | ||
| 27 | #include <openssl/x509.h> | ||
| 28 | #include <openssl/x509v3.h> | ||
| 29 | #include <openssl/conf.h> | ||
| 30 | |||
| 31 | #include <readline/readline.h> | ||
| 32 | |||
| 33 | #include "vchat.h" | ||
| 34 | #include "vchat-tls.h" | ||
| 35 | |||
| 36 | const char *vchat_ssl_version = "vchat-tlsl.c $Id$"; | ||
| 37 | |||
| 38 | /* connection BIO for openssl */ | ||
| 39 | static BIO *server_conn = NULL; | ||
| 40 | |||
| 41 | typedef int (*vc_x509verify_cb_t)(int, X509_STORE_CTX *); | ||
| 42 | struct vc_x509store_t { | ||
| 43 | char *cafile; | ||
| 44 | char *capath; | ||
| 45 | char *crlfile; | ||
| 46 | vc_x509verify_cb_t callback; | ||
| 47 | vc_askpass_cb_t askpass_callback; | ||
| 48 | STACK_OF(X509) *certs; | ||
| 49 | STACK_OF(X509_CRL) *crls; | ||
| 50 | char *use_certfile; | ||
| 51 | STACK_OF(X509) *use_certs; | ||
| 52 | char *use_keyfile; | ||
| 53 | EVP_PKEY *use_key; | ||
| 54 | int flags; | ||
| 55 | }; | ||
| 56 | |||
| 57 | static SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store ); | ||
| 58 | static int vc_verify_callback(int, X509_STORE_CTX *); | ||
| 59 | static X509_STORE * vc_x509store_create(vc_x509store_t *); | ||
| 60 | static void vc_x509store_clearflags(vc_x509store_t *, int); | ||
| 61 | static void vc_x509store_setcapath(vc_x509store_t *, char *); | ||
| 62 | static void vc_x509store_setcrlfile(vc_x509store_t *, char *); | ||
| 63 | static void vc_x509store_addcert(vc_x509store_t *, X509 *); | ||
| 64 | static void vc_x509store_setcb(vc_x509store_t *, vc_x509verify_cb_t); | ||
| 65 | |||
| 66 | #define VC_CTX_ERR_EXIT(se, cx) do { \ | ||
| 67 | snprintf(tmpstr, TMPSTRSIZE, "CREATE CTX: %s", \ | ||
| 68 | ERR_error_string (ERR_get_error (), NULL)); \ | ||
| 69 | writecf(FS_ERR, tmpstr); \ | ||
| 70 | if(se) X509_STORE_free(se); \ | ||
| 71 | if(cx) SSL_CTX_free(cx); \ | ||
| 72 | return(0); \ | ||
| 73 | } while(0) | ||
| 74 | |||
| 75 | #define VC_SETCERT_ERR_EXIT(se, cx, err) do { \ | ||
| 76 | snprintf(tmpstr, TMPSTRSIZE, "CREATE CTX: %s", err); \ | ||
| 77 | writecf(FS_ERR, tmpstr); \ | ||
| 78 | if(se) X509_STORE_free(se); \ | ||
| 79 | if(cx) SSL_CTX_free(cx); \ | ||
| 80 | return(NULL); \ | ||
| 81 | } while(0) | ||
| 82 | |||
| 83 | static SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store ) | ||
| 84 | { | ||
| 85 | int i = 0; | ||
| 86 | int n = 0; | ||
| 87 | int flags = 0; | ||
| 88 | int r = 0; | ||
| 89 | SSL_CTX *ctx = NULL; | ||
| 90 | X509_STORE *store = NULL; | ||
| 91 | vc_x509verify_cb_t verify_callback = NULL; | ||
| 92 | |||
| 93 | /* Explicitly use TLSv1 (or maybe later) */ | ||
| 94 | if( !(ctx = SSL_CTX_new(TLS_client_method())) ) | ||
| 95 | VC_CTX_ERR_EXIT(store, ctx); | ||
| 96 | |||
| 97 | if( !(store = vc_x509store_create(vc_store)) ) | ||
| 98 | VC_CTX_ERR_EXIT(store, ctx); | ||
| 99 | |||
| 100 | SSL_CTX_set_cert_store(ctx, store); | ||
| 101 | store = NULL; | ||
| 102 | /* Disable some insecure protocols explicitly */ | ||
| 103 | SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); | ||
| 104 | if (getstroption(CF_CIPHERSUITE)) | ||
| 105 | SSL_CTX_set_cipher_list(ctx, getstroption(CF_CIPHERSUITE)); | ||
| 106 | else | ||
| 107 | SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA"); | ||
| 108 | |||
| 109 | SSL_CTX_set_verify_depth (ctx, getintoption(CF_VERIFYSSL)); | ||
| 110 | |||
| 111 | if( !(verify_callback = vc_store->callback) ) | ||
| 112 | verify_callback = vc_verify_callback; | ||
| 113 | |||
| 114 | if( !(vc_store->flags & VC_X509S_SSL_VERIFY_MASK) ) { | ||
| 115 | writecf(FS_DBG, tmpstr); | ||
| 116 | flags = SSL_VERIFY_NONE; | ||
| 117 | } | ||
| 118 | else { | ||
| 119 | if(vc_store->flags & VC_X509S_SSL_VERIFY_PEER) | ||
| 120 | flags |= SSL_VERIFY_PEER; | ||
| 121 | if(vc_store->flags & VC_X509S_SSL_VERIFY_FAIL_IF_NO_PEER_CERT) | ||
| 122 | flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; | ||
| 123 | if(vc_store->flags & VC_X509S_SSL_VERIFY_CLIENT_ONCE) | ||
| 124 | flags |= SSL_VERIFY_CLIENT_ONCE; | ||
| 125 | } | ||
| 126 | |||
| 127 | SSL_CTX_set_verify(ctx, flags, verify_callback); | ||
| 128 | |||
| 129 | if(vc_store->flags & VC_X509S_USE_CERTIFICATE) { | ||
| 130 | if(vc_store->use_certfile) | ||
| 131 | SSL_CTX_use_certificate_chain_file(ctx, vc_store->use_certfile); | ||
| 132 | else { | ||
| 133 | SSL_CTX_use_certificate(ctx, | ||
| 134 | sk_X509_value(vc_store->use_certs, 0)); | ||
| 135 | for(i=0,n=sk_X509_num(vc_store->use_certs); i<n; i++) | ||
| 136 | SSL_CTX_add_extra_chain_cert(ctx, | ||
| 137 | sk_X509_value(vc_store->use_certs, i)); | ||
| 138 | } | ||
| 139 | |||
| 140 | SSL_CTX_set_default_passwd_cb(ctx, vc_store->askpass_callback); | ||
| 141 | |||
| 142 | if(vc_store->use_keyfile) { | ||
| 143 | r=SSL_CTX_use_PrivateKey_file(ctx, vc_store->use_keyfile, | ||
| 144 | SSL_FILETYPE_PEM); | ||
| 145 | } else if(vc_store->use_key) | ||
| 146 | r=SSL_CTX_use_PrivateKey(ctx, vc_store->use_key); | ||
| 147 | |||
| 148 | if( r!=1 || !SSL_CTX_check_private_key(ctx)) | ||
| 149 | VC_SETCERT_ERR_EXIT(store, ctx, "Load private key failed"); | ||
| 150 | } | ||
| 151 | |||
| 152 | SSL_CTX_set_app_data(ctx, vc_store); | ||
| 153 | return(ctx); | ||
| 154 | } | ||
| 155 | |||
| 156 | int vc_tls_connect( int serverfd, vc_x509store_t *vc_store ) | ||
| 157 | { | ||
| 158 | SSL_CTX * ctx = vc_create_sslctx(vc_store); | ||
| 159 | X509 *peercert = NULL; | ||
| 160 | BIO *ssl_conn = NULL; | ||
| 161 | const SSL *sslp = NULL; | ||
| 162 | const SSL_CIPHER * cipher = NULL; | ||
| 163 | |||
| 164 | server_conn = BIO_new_socket( serverfd, 1 ); | ||
| 165 | |||
| 166 | /* To display and check server fingerprint */ | ||
| 167 | char fingerprint[EVP_MAX_MD_SIZE*4]; | ||
| 168 | unsigned char fingerprint_bin[EVP_MAX_MD_SIZE]; | ||
| 169 | unsigned int fingerprint_len; | ||
| 170 | |||
| 171 | FILE *fingerprint_file = NULL; | ||
| 172 | char * fp = fingerprint; | ||
| 173 | |||
| 174 | long result, j; | ||
| 175 | |||
| 176 | if( !ctx ) | ||
| 177 | goto all_errors; | ||
| 178 | |||
| 179 | ssl_conn = BIO_new_ssl(ctx, 1); | ||
| 180 | SSL_CTX_free(ctx); | ||
| 181 | |||
| 182 | if( !ssl_conn ) | ||
| 183 | goto ssl_error; | ||
| 184 | |||
| 185 | BIO_push( ssl_conn, server_conn ); | ||
| 186 | server_conn = ssl_conn; | ||
| 187 | fflush(stdout); | ||
| 188 | |||
| 189 | if( BIO_do_handshake( server_conn ) <= 0 ) | ||
| 190 | goto ssl_error; | ||
| 191 | |||
| 192 | /* Show information about cipher used */ | ||
| 193 | /* Get cipher object */ | ||
| 194 | BIO_get_ssl(ssl_conn, &sslp); | ||
| 195 | if (!sslp) | ||
| 196 | goto ssl_error; | ||
| 197 | |||
| 198 | cipher = SSL_get_current_cipher(sslp); | ||
| 199 | if (cipher) { | ||
| 200 | char cipher_desc[TMPSTRSIZE]; | ||
| 201 | snprintf(tmpstr, TMPSTRSIZE, "[SSL CIPHER ] %s", SSL_CIPHER_description(cipher, cipher_desc, TMPSTRSIZE)); | ||
| 202 | writecf(FS_SERV, tmpstr); | ||
| 203 | } else { | ||
| 204 | snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR ] Cipher not known / SSL object can't be queried!"); | ||
| 205 | writecf(FS_ERR, tmpstr); | ||
| 206 | } | ||
| 207 | |||
| 208 | /* Accept being connected, _if_ verification passed */ | ||
| 209 | peercert = SSL_get_peer_certificate(sslp); | ||
| 210 | if (!peercert) | ||
| 211 | goto ssl_error; | ||
| 212 | |||
| 213 | /* show basic information about peer cert */ | ||
| 214 | snprintf(tmpstr, TMPSTRSIZE, "[SSL SUBJECT ] %s", X509_NAME_oneline(X509_get_subject_name(peercert),0,0)); | ||
| 215 | writecf(FS_SERV, tmpstr); | ||
| 216 | snprintf(tmpstr, TMPSTRSIZE, "[SSL ISSUER ] %s", X509_NAME_oneline(X509_get_issuer_name(peercert),0,0)); | ||
| 217 | writecf(FS_SERV, tmpstr); | ||
| 218 | |||
| 219 | /* calculate fingerprint */ | ||
| 220 | if (!X509_digest(peercert,EVP_sha1(),fingerprint_bin,&fingerprint_len)) | ||
| 221 | goto ssl_error; | ||
| 222 | |||
| 223 | assert ( ( fingerprint_len > 1 ) && (fingerprint_len <= EVP_MAX_MD_SIZE )); | ||
| 224 | for (j=0; j<(int)fingerprint_len; j++) | ||
| 225 | fp += sprintf(fp, "%02X:", fingerprint_bin[j]); | ||
| 226 | assert ( fp > fingerprint ); | ||
| 227 | fp[-1] = 0; | ||
| 228 | snprintf(tmpstr, TMPSTRSIZE, "[SSL FINGERPRINT ] %s (from server)", fingerprint); | ||
| 229 | writecf(FS_SERV, tmpstr); | ||
| 230 | |||
| 231 | /* we don't need the peercert anymore */ | ||
| 232 | X509_free(peercert); | ||
| 233 | |||
| 234 | /* verify fingerprint */ | ||
| 235 | if (getintoption(CF_PINFINGER)) { | ||
| 236 | |||
| 237 | fingerprint_file = fopen(tilde_expand(getstroption(CF_FINGERPRINT)), "r"); | ||
| 238 | if (fingerprint_file) { | ||
| 239 | |||
| 240 | /* Read fingerprint from file */ | ||
| 241 | char old_fingerprint[EVP_MAX_MD_SIZE*4]; | ||
| 242 | char * r = fgets(old_fingerprint, sizeof(old_fingerprint), fingerprint_file); | ||
| 243 | fclose(fingerprint_file); | ||
| 244 | |||
| 245 | if (r) { | ||
| 246 | /* chomp */ | ||
| 247 | char *nl = strchr(r, '\n'); | ||
| 248 | if (nl) *nl = 0; | ||
| 249 | |||
| 250 | /* verify fingerprint matches stored version */ | ||
| 251 | if (!strcmp(fingerprint, old_fingerprint)) | ||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | |||
| 255 | snprintf(tmpstr, TMPSTRSIZE, "[SSL FINGERPRINT ] %s (from %s)", r ? old_fingerprint : "<FILE READ ERROR>", getstroption(CF_FINGERPRINT)); | ||
| 256 | writecf(FS_ERR, tmpstr); | ||
| 257 | writecf(FS_ERR, "[SSL CONNECT ERROR] Fingerprint mismatch! Server cert updated?"); | ||
| 258 | return 1; | ||
| 259 | } | ||
| 260 | |||
| 261 | fingerprint_file = fopen(tilde_expand(getstroption(CF_FINGERPRINT)), "w"); | ||
| 262 | if (!fingerprint_file) { | ||
| 263 | snprintf (tmpstr, TMPSTRSIZE, "[WARNING] Can't write fingerprint file, %s.", strerror(errno)); | ||
| 264 | writecf(FS_ERR, tmpstr); | ||
| 265 | } else { | ||
| 266 | fputs(fingerprint, fingerprint_file); | ||
| 267 | fclose(fingerprint_file); | ||
| 268 | writecf(FS_SERV, "Stored fingerprint."); | ||
| 269 | } | ||
| 270 | return 0; | ||
| 271 | } | ||
| 272 | |||
| 273 | /* If verify of x509 chain was requested, do the check here */ | ||
| 274 | result = SSL_get_verify_result(sslp); | ||
| 275 | |||
| 276 | if (result == X509_V_OK) | ||
| 277 | return 0; | ||
| 278 | |||
| 279 | if (getintoption(CF_IGNSSL)) { | ||
| 280 | writecf(FS_ERR, "[SSL VERIFY ERROR ] FAILURE IGNORED!!!"); | ||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | |||
| 284 | ssl_error: | ||
| 285 | snprintf(tmpstr, TMPSTRSIZE, "[SSL CONNECT ERROR] %s", ERR_error_string (ERR_get_error (), NULL)); | ||
| 286 | writecf(FS_ERR, tmpstr); | ||
| 287 | all_errors: | ||
| 288 | BIO_free_all( server_conn ); | ||
| 289 | server_conn = NULL; | ||
| 290 | return 1; | ||
| 291 | } | ||
| 292 | |||
| 293 | #define VC_STORE_ERR_EXIT(s) do { \ | ||
| 294 | fprintf(stderr, "[E] SSL_STORE: %s\n", ERR_error_string (ERR_get_error (), NULL)); \ | ||
| 295 | if(s) X509_STORE_free(s); \ | ||
| 296 | return(0); \ | ||
| 297 | } while(0) | ||
| 298 | |||
| 299 | X509_STORE *vc_x509store_create(vc_x509store_t *vc_store) | ||
| 300 | { | ||
| 301 | int i = 0; | ||
| 302 | int n = 0; | ||
| 303 | X509_STORE *store = NULL; | ||
| 304 | X509_LOOKUP *lookup = NULL; | ||
| 305 | |||
| 306 | store = X509_STORE_new(); | ||
| 307 | |||
| 308 | if(vc_store->callback) | ||
| 309 | X509_STORE_set_verify_cb_func(store, vc_store->callback); | ||
| 310 | else | ||
| 311 | X509_STORE_set_verify_cb_func(store, vc_verify_callback); | ||
| 312 | |||
| 313 | if( !(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) ) | ||
| 314 | VC_STORE_ERR_EXIT(store); | ||
| 315 | |||
| 316 | if(!vc_store->cafile) { | ||
| 317 | if( !(vc_store->flags & VC_X509S_NODEF_CAFILE) ) | ||
| 318 | X509_LOOKUP_load_file(lookup, 0, X509_FILETYPE_DEFAULT); | ||
| 319 | } else if( !X509_LOOKUP_load_file(lookup, vc_store->cafile, | ||
| 320 | X509_FILETYPE_PEM) ) | ||
| 321 | VC_STORE_ERR_EXIT(store); | ||
| 322 | |||
| 323 | if(vc_store->crlfile) { | ||
| 324 | if( !X509_load_crl_file(lookup, vc_store->crlfile, | ||
| 325 | X509_FILETYPE_PEM) ) | ||
| 326 | VC_STORE_ERR_EXIT(store); | ||
| 327 | |||
| 328 | X509_STORE_set_flags( store, | ||
| 329 | X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL ); | ||
| 330 | } | ||
| 331 | |||
| 332 | if( !(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir())) ) | ||
| 333 | VC_STORE_ERR_EXIT(store); | ||
| 334 | |||
| 335 | if( !vc_store->capath ) { | ||
| 336 | if( !(vc_store->flags & VC_X509S_NODEF_CAPATH) ) | ||
| 337 | X509_LOOKUP_add_dir(lookup, 0, X509_FILETYPE_DEFAULT); | ||
| 338 | } else if( !X509_LOOKUP_add_dir(lookup, vc_store->capath, | ||
| 339 | X509_FILETYPE_PEM) ) | ||
| 340 | VC_STORE_ERR_EXIT(store); | ||
| 341 | |||
| 342 | for( i=0, n=sk_X509_num(vc_store->certs); i<n; i++) | ||
| 343 | if( !X509_STORE_add_cert(store, sk_X509_value(vc_store->certs, i)) ) | ||
| 344 | VC_STORE_ERR_EXIT(store); | ||
| 345 | |||
| 346 | for( i=0, n=sk_X509_CRL_num(vc_store->crls); i<n; i++) | ||
| 347 | if( !X509_STORE_add_crl(store, | ||
| 348 | sk_X509_CRL_value(vc_store->crls, i)) ) | ||
| 349 | VC_STORE_ERR_EXIT(store); | ||
| 350 | |||
| 351 | return(store); | ||
| 352 | } | ||
| 353 | |||
| 354 | int vc_verify_callback(int ok, X509_STORE_CTX *store) | ||
| 355 | { | ||
| 356 | if(!ok) { | ||
| 357 | snprintf(tmpstr, TMPSTRSIZE, "[SSL VERIFY ERROR ] %s", | ||
| 358 | X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); | ||
| 359 | writecf(FS_ERR, tmpstr); | ||
| 360 | } | ||
| 361 | return (ok | getintoption(CF_IGNSSL)); | ||
| 362 | } | ||
| 363 | |||
| 364 | void vc_x509store_setflags(vc_x509store_t *store, int flags) | ||
| 365 | { | ||
| 366 | store->flags |= flags; | ||
| 367 | } | ||
| 368 | |||
| 369 | void vc_x509store_clearflags(vc_x509store_t *store, int flags) | ||
| 370 | { | ||
| 371 | store->flags &= ~flags; | ||
| 372 | } | ||
| 373 | |||
| 374 | void vc_x509store_setcb(vc_x509store_t *store, | ||
| 375 | vc_x509verify_cb_t callback) | ||
| 376 | { | ||
| 377 | store->callback = callback; | ||
| 378 | } | ||
| 379 | |||
| 380 | void vc_x509store_set_pkeycb(vc_x509store_t *store, | ||
| 381 | vc_askpass_cb_t callback) | ||
| 382 | { | ||
| 383 | store->askpass_callback = callback; | ||
| 384 | } | ||
| 385 | |||
| 386 | void vc_x509store_addcert(vc_x509store_t *store, X509 *cert) | ||
| 387 | { | ||
| 388 | sk_X509_push(store->certs, cert); | ||
| 389 | } | ||
| 390 | |||
| 391 | void vc_x509store_setcafile(vc_x509store_t *store, char *file) | ||
| 392 | { | ||
| 393 | free(store->cafile); | ||
| 394 | store->cafile = ( file ? strdup(file) : 0 ); | ||
| 395 | } | ||
| 396 | |||
| 397 | void vc_x509store_setcapath(vc_x509store_t *store, char *path) | ||
| 398 | { | ||
| 399 | free(store->capath); | ||
| 400 | store->capath = ( path ? strdup(path) : 0 ); | ||
| 401 | } | ||
| 402 | |||
| 403 | void vc_x509store_setcrlfile(vc_x509store_t *store, char *file) | ||
| 404 | { | ||
| 405 | free(store->crlfile); | ||
| 406 | store->crlfile = ( file ? strdup(file) : 0 ); | ||
| 407 | } | ||
| 408 | |||
| 409 | void vc_x509store_setkeyfile(vc_x509store_t *store, char *file) | ||
| 410 | { | ||
| 411 | free(store->use_keyfile); | ||
| 412 | store->use_keyfile = ( file ? strdup(file) : 0 ); | ||
| 413 | } | ||
| 414 | |||
| 415 | void vc_x509store_setcertfile(vc_x509store_t *store, char *file) | ||
| 416 | { | ||
| 417 | free(store->use_certfile); | ||
| 418 | store->use_certfile = ( file ? strdup(file) : 0 ); | ||
| 419 | } | ||
| 420 | |||
| 421 | vc_x509store_t *vc_init_x509store() | ||
| 422 | { | ||
| 423 | vc_x509store_t *s = malloc(sizeof(vc_x509store_t)); | ||
| 424 | if (s) { | ||
| 425 | |||
| 426 | static int sslinit; | ||
| 427 | if( !sslinit++ ) { | ||
| 428 | SSL_library_init (); | ||
| 429 | SSL_load_error_strings(); | ||
| 430 | } | ||
| 431 | |||
| 432 | s->cafile = NULL; | ||
| 433 | s->capath = NULL; | ||
| 434 | s->crlfile = NULL; | ||
| 435 | s->callback = NULL; | ||
| 436 | s->askpass_callback = NULL; | ||
| 437 | s->certs = sk_X509_new_null(); | ||
| 438 | s->crls = sk_X509_CRL_new_null(); | ||
| 439 | s->use_certfile = NULL; | ||
| 440 | s->use_certs = sk_X509_new_null(); | ||
| 441 | s->use_keyfile = NULL; | ||
| 442 | s->use_key = NULL; | ||
| 443 | s->flags = 0; | ||
| 444 | } | ||
| 445 | return s; | ||
| 446 | } | ||
| 447 | |||
| 448 | void vc_cleanup_x509store(vc_x509store_t *s) | ||
| 449 | { | ||
| 450 | free(s->cafile); | ||
| 451 | free(s->capath); | ||
| 452 | free(s->crlfile); | ||
| 453 | free(s->use_certfile); | ||
| 454 | free(s->use_keyfile); | ||
| 455 | free(s->use_key); | ||
| 456 | sk_X509_free(s->certs); | ||
| 457 | sk_X509_CRL_free(s->crls); | ||
| 458 | sk_X509_free(s->use_certs); | ||
| 459 | free(s); | ||
| 460 | } | ||
| 461 | |||
| 462 | ssize_t vc_tls_sendmessage(const void *buf, size_t size) { | ||
| 463 | return BIO_write(server_conn, buf, size); | ||
| 464 | } | ||
| 465 | |||
| 466 | ssize_t vc_tls_receivemessage(void *buf, size_t size) { | ||
| 467 | return BIO_read (server_conn, buf, size); | ||
| 468 | } | ||
| 469 | |||
| 470 | void vc_tls_cleanup() { | ||
| 471 | BIO_free_all( server_conn ); | ||
| 472 | server_conn = NULL; | ||
| 473 | } | ||
| 474 | |||
| 475 | const char *vchat_ssl_version_external = "OpenSSL implementation; version unknown"; | ||
| 476 | void vchat_ssl_get_version_external() | ||
| 477 | { | ||
| 478 | char tmpstr[TMPSTRSIZE]; | ||
| 479 | snprintf(tmpstr, TMPSTRSIZE, "%s with %s", SSLeay_version(SSLEAY_VERSION), SSLeay_version(SSLEAY_CFLAGS)); | ||
| 480 | vchat_ssl_version_external = strdup(tmpstr); | ||
| 481 | } | ||
