/** * \brief do TLS negotiation with client application * \param[in] *C The context of verse server * \return This function returns 1, when TLS connection was established and * it returns 0, when TLS was not established. */ int vs_TLS_handshake(struct vContext *C) { struct VS_CTX *vs_ctx = CTX_server_ctx(C); struct IO_CTX *io_ctx = CTX_io_ctx(C); struct VStreamConn *stream_conn = CTX_current_stream_conn(C); int flag, ret; /* Make sure socket is blocking */ flag = fcntl(stream_conn->io_ctx.sockfd, F_GETFL, 0); if( (fcntl(stream_conn->io_ctx.sockfd, F_SETFL, flag & ~O_NONBLOCK)) == -1) { if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "fcntl(): %s\n", strerror(errno)); return 0; } /* Set up SSL */ if( (stream_conn->io_ctx.ssl = SSL_new(vs_ctx->tls_ctx)) == NULL) { v_print_log(VRS_PRINT_ERROR, "Setting up SSL failed.\n"); ERR_print_errors_fp(v_log_file()); SSL_free(stream_conn->io_ctx.ssl); stream_conn->io_ctx.ssl = NULL; close(io_ctx->sockfd); return 0; } /* Bind socket and SSL */ if (SSL_set_fd(stream_conn->io_ctx.ssl, io_ctx->sockfd) == 0) { v_print_log(VRS_PRINT_ERROR, "Failed binding socket descriptor and SSL.\n"); ERR_print_errors_fp(v_log_file()); SSL_free(stream_conn->io_ctx.ssl); stream_conn->io_ctx.ssl = NULL; close(io_ctx->sockfd); return 0; } SSL_set_mode(stream_conn->io_ctx.ssl, SSL_MODE_AUTO_RETRY); /* Do TLS handshake and negotiation */ if( (ret = SSL_accept(stream_conn->io_ctx.ssl)) != 1) { int err = SSL_get_error(stream_conn->io_ctx.ssl, ret); v_print_log(VRS_PRINT_ERROR, "SSL handshake failed: %d -> %d\n", ret, err); ERR_print_errors_fp(v_log_file()); SSL_free(stream_conn->io_ctx.ssl); stream_conn->io_ctx.ssl = NULL; close(io_ctx->sockfd); return 0; } v_print_log(VRS_PRINT_DEBUG_MSG, "SSL handshake succeed.\n"); return 1; }
/** * \brief This function sets debug level of verse server. */ static int vs_set_debug_level(char *debug_level) { FILE *log_file = v_log_file(); if( strcmp(debug_level, "debug") == 0) { v_init_print_log(VRS_PRINT_DEBUG_MSG, log_file); return 1; } else if( strcmp(debug_level, "warning") == 0 ) { v_init_print_log(VRS_PRINT_WARNING, log_file); return 1; } else if( strcmp(debug_level, "error") == 0 ) { v_init_print_log(VRS_PRINT_ERROR, log_file); return 1; } else if( strcmp(debug_level, "info") == 0 ) { v_init_print_log(VRS_PRINT_INFO, log_file); return 1; } else if( strcmp(debug_level, "none") == 0 ) { v_init_print_log(VRS_PRINT_NONE, log_file); return 1; } else { v_print_log(VRS_PRINT_ERROR, "Unsupported debug level: %s\n", debug_level); return 0; } }
/* * \brief Initialize OpenSSl of Verse server */ static int vs_init_ssl(VS_CTX *vs_ctx) { /* Set up the library */ SSL_library_init(); ERR_load_BIO_strings(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); /* Set up SSL context for TLS */ if( (vs_ctx->tls_ctx = SSL_CTX_new(TLSv1_server_method())) == NULL ) { v_print_log(VRS_PRINT_ERROR, "Setting up SSL_CTX failed.\n"); ERR_print_errors_fp(v_log_file()); return -1; } /* Load certificate chain file from CA */ if(vs_ctx->ca_cert_file != NULL) { if(SSL_CTX_use_certificate_chain_file(vs_ctx->tls_ctx, vs_ctx->ca_cert_file) != 1) { v_print_log(VRS_PRINT_ERROR, "TLS: Loading certificate chain file: %s failed.\n", vs_ctx->ca_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } } /* Load certificate with public key for TLS */ if(SSL_CTX_use_certificate_file(vs_ctx->tls_ctx, vs_ctx->public_cert_file, SSL_FILETYPE_PEM) != 1) { v_print_log(VRS_PRINT_ERROR, "TLS: Loading certificate file: %s failed.\n", vs_ctx->public_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } /* Load private key for TLS */ if(SSL_CTX_use_PrivateKey_file(vs_ctx->tls_ctx, vs_ctx->private_cert_file, SSL_FILETYPE_PEM) != 1) { v_print_log(VRS_PRINT_ERROR, "TLS: Loading private key file: %s failed.\n", vs_ctx->private_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } /* Check the consistency of a private key with the corresponding * certificate loaded into ssl_ctx */ if(SSL_CTX_check_private_key(vs_ctx->tls_ctx) != 1) { v_print_log(VRS_PRINT_ERROR, "TLS: Private key does not match the certificate public key\n"); ERR_print_errors_fp(v_log_file()); return -1; } /* When CA certificate file was set, then try to load it */ if(vs_ctx->ca_cert_file != NULL) { if(SSL_CTX_load_verify_locations(vs_ctx->tls_ctx, vs_ctx->ca_cert_file, NULL) != 1) { v_print_log(VRS_PRINT_ERROR, "TLS: Loading CA certificate file: %s failed.\n", vs_ctx->ca_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } } #if OPENSSL_VERSION_NUMBER>=0x10000000 /* Set up SSL context for DTLS */ if( (vs_ctx->dtls_ctx = SSL_CTX_new(DTLSv1_server_method())) == NULL ) { v_print_log(VRS_PRINT_ERROR, "Setting up SSL_CTX failed.\n"); ERR_print_errors_fp(v_log_file()); return -1; } /* Load certificate chain file from CA */ if(vs_ctx->ca_cert_file != NULL) { if(SSL_CTX_use_certificate_chain_file(vs_ctx->dtls_ctx, vs_ctx->ca_cert_file) != 1) { v_print_log(VRS_PRINT_ERROR, "DTLS: Loading certificate chain file: %s failed.\n", vs_ctx->ca_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } } /* Load certificate with public key for DTLS */ if (SSL_CTX_use_certificate_file(vs_ctx->dtls_ctx, vs_ctx->public_cert_file, SSL_FILETYPE_PEM) != 1) { v_print_log(VRS_PRINT_ERROR, "DTLS: Loading certificate file: %s failed.\n", vs_ctx->public_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } /* Load private key for DTLS */ if(SSL_CTX_use_PrivateKey_file(vs_ctx->dtls_ctx, vs_ctx->private_cert_file, SSL_FILETYPE_PEM) != 1) { v_print_log(VRS_PRINT_ERROR, "DTLS: Loading private key file: %s failed.\n", vs_ctx->private_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } /* Check the consistency of a private key with the corresponding * certificate loaded into ssl_ctx */ if(SSL_CTX_check_private_key(vs_ctx->dtls_ctx) != 1) { v_print_log(VRS_PRINT_ERROR, "DTLS: Private key does not match the certificate public key\n"); ERR_print_errors_fp(v_log_file()); return -1; } /* When CA certificate file was set, then try to load it */ if(vs_ctx->ca_cert_file != NULL) { if(SSL_CTX_load_verify_locations(vs_ctx->dtls_ctx, vs_ctx->ca_cert_file, NULL) != 1) { v_print_log(VRS_PRINT_ERROR, "DTLS: Loading CA certificate file: %s failed.\n", vs_ctx->ca_cert_file); ERR_print_errors_fp(v_log_file()); return -1; } } /* Set up callback functions for DTLS cookie */ SSL_CTX_set_cookie_generate_cb(vs_ctx->dtls_ctx, vs_dtls_generate_cookie); SSL_CTX_set_cookie_verify_cb(vs_ctx->dtls_ctx, vs_dtls_verify_cookie); /* Accept all cipher including NULL cipher (testing) */ if( SSL_CTX_set_cipher_list(vs_ctx->dtls_ctx, "ALL:NULL:eNULL:aNULL") == 0) { v_print_log(VRS_PRINT_ERROR, "Setting ciphers for DTLS failed.\n"); ERR_print_errors_fp(v_log_file()); return 0; } /* DTLS require this */ SSL_CTX_set_read_ahead(vs_ctx->dtls_ctx, 1); #else vs_ctx->dtls_ctx = NULL; #endif return 1; }
/** * \brief Initialize verse client context */ int vc_init_ctx(struct VC_CTX *vc_ctx) { int i; /* Allocate memory for session slots and make session slots NULL */ vc_ctx->vsessions = (struct VSession**)malloc(sizeof(struct VSession*)*vc_ctx->max_sessions); vc_ctx->session_counter = 0; for(i=0; i<vc_ctx->max_sessions; i++) { vc_ctx->vsessions[i] = NULL; } /* Initialize callback function */ vc_init_func_storage(&vc_ctx->vfs); #ifdef WITH_OPENSSL /* Set up the library */ SSL_library_init(); ERR_load_BIO_strings(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); /* Set up SSL context for TLS */ if( (vc_ctx->tls_ctx = SSL_CTX_new(TLSv1_client_method())) == NULL ) { v_print_log(VRS_PRINT_ERROR, "Setting up SSL_CTX for TLS failed.\n"); ERR_print_errors_fp(v_log_file()); return 0; } /* Load the trust store for TLS */ if(SSL_CTX_load_verify_locations(vc_ctx->tls_ctx, NULL, vc_ctx->ca_path) != 1) { v_print_log(VRS_PRINT_ERROR, "Loading path with CA certificates failed.\n"); ERR_print_errors_fp(v_log_file()); } else { v_print_log(VRS_PRINT_DEBUG_MSG, "Path %s with CA certificates loaded successfully.\n", vc_ctx->ca_path); } #endif #if (defined WITH_OPENSSL) && OPENSSL_VERSION_NUMBER>=0x10000000 /* Set up SSL context for DTSL */ if( (vc_ctx->dtls_ctx = SSL_CTX_new(DTLSv1_client_method())) == NULL ) { v_print_log(VRS_PRINT_ERROR, "Setting up SSL_CTX for DTLS failed.\n"); ERR_print_errors_fp(v_log_file()); return 0; } /* Load the trust store for DTLS */ if(SSL_CTX_load_verify_locations(vc_ctx->dtls_ctx, NULL, vc_ctx->ca_path) != 1) { v_print_log(VRS_PRINT_ERROR, "Loading path with CA certificates failed.\n"); ERR_print_errors_fp(v_log_file()); } else { v_print_log(VRS_PRINT_DEBUG_MSG, "Path %s with CA certificates loaded successfully.\n", vc_ctx->ca_path); } /* Negotiate ciphers with server * For testing: (encryption:none, mac:sha) eNULL:!MDP5 * For real use: ALL:ALL */ if( SSL_CTX_set_cipher_list(vc_ctx->dtls_ctx, "eNULL:!MD5") == 0) { v_print_log(VRS_PRINT_ERROR, "Setting ciphers for DTLS failed.\n"); ERR_print_errors_fp(v_log_file()); return 0; } /* This is necessary for DTLS */ SSL_CTX_set_read_ahead(vc_ctx->dtls_ctx, 1); #else vc_ctx->dtls_ctx = NULL; #endif /* Default name and version */ vc_ctx->client_name = NULL; vc_ctx->client_version = NULL; pthread_mutex_init(&vc_ctx->mutex, NULL); return 1; }