bool ssl_connect_wget (int fd) { static const int cert_type_priority[] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 }; struct wgnutls_transport_context *ctx; gnutls_session session; int err; int allowed_protocols[4] = {0, 0, 0, 0}; gnutls_init (&session, GNUTLS_CLIENT); gnutls_set_default_priority (session); gnutls_certificate_type_set_priority (session, cert_type_priority); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials); #ifndef FD_TO_SOCKET # define FD_TO_SOCKET(X) (X) #endif gnutls_transport_set_ptr (session, (gnutls_transport_ptr) FD_TO_SOCKET (fd)); err = 0; switch (opt.secure_protocol) { case secure_protocol_auto: break; case secure_protocol_sslv2: case secure_protocol_sslv3: allowed_protocols[0] = GNUTLS_SSL3; err = gnutls_protocol_set_priority (session, allowed_protocols); break; case secure_protocol_tlsv1: allowed_protocols[0] = GNUTLS_TLS1_0; allowed_protocols[1] = GNUTLS_TLS1_1; allowed_protocols[2] = GNUTLS_TLS1_2; err = gnutls_protocol_set_priority (session, allowed_protocols); break; default: abort (); } if (err < 0) { logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err)); gnutls_deinit (session); return false; } err = gnutls_handshake (session); if (err < 0) { logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err)); gnutls_deinit (session); return false; } ctx = xnew0 (struct wgnutls_transport_context); ctx->session = session; fd_register_transport (fd, &wgnutls_transport, ctx); return true; }
static int vnc_set_gnutls_priority(gnutls_session_t s, int x509) { static const int cert_types[] = { GNUTLS_CRT_X509, 0 }; static const int protocols[] = { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 }; static const int kx_anon[] = { GNUTLS_KX_ANON_DH, 0 }; static const int kx_x509[] = { GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0 }; int rc; rc = gnutls_kx_set_priority(s, x509 ? kx_x509 : kx_anon); if (rc != GNUTLS_E_SUCCESS) { return -1; } rc = gnutls_certificate_type_set_priority(s, cert_types); if (rc != GNUTLS_E_SUCCESS) { return -1; } rc = gnutls_protocol_set_priority(s, protocols); if (rc != GNUTLS_E_SUCCESS) { return -1; } return 0; }
struct tls_connection * tls_connection_init(void *ssl_ctx) { struct tls_connection *conn; const int cert_types[2] = { GNUTLS_CRT_X509, 0 }; const int protos[2] = { GNUTLS_TLS1, 0 }; conn = malloc(sizeof(*conn)); if (conn == NULL) return NULL; memset(conn, 0, sizeof(*conn)); if (gnutls_init(&conn->session, GNUTLS_CLIENT) < 0) { wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS " "connection"); free(conn); return NULL; } gnutls_set_default_priority(conn->session); gnutls_certificate_type_set_priority(conn->session, cert_types); gnutls_protocol_set_priority(conn->session, protos); gnutls_transport_set_pull_function(conn->session, tls_pull_func); gnutls_transport_set_push_function(conn->session, tls_push_func); gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn); gnutls_certificate_allocate_credentials(&conn->xcred); return conn; }
static void ADD_PROTOCOL (gnutls_session session, int protocol) { static int _proto_priority[] = { 0, 0 }; _proto_priority[0] = protocol; gnutls_protocol_set_priority (session, _proto_priority); }
static int tls_handshake (struct ikstls_data **datap, ikstransport *trans, void *sock) { const int protocol_priority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 }; const int kx_priority[] = { GNUTLS_KX_RSA, 0 }; const int cipher_priority[] = { GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0}; const int comp_priority[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 }; const int mac_priority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 }; struct ikstls_data *data; int ret; *datap = NULL; data = iks_malloc (sizeof(*data)); if (!data) return IKS_NOMEM; memset (data, 0, sizeof(*data)); data->trans = trans; data->sock = sock; data->timeout = -1; if (gnutls_global_init () != 0) { iks_free (data); return IKS_NOMEM; } if (gnutls_certificate_allocate_credentials (&data->cred) < 0) { iks_free (data); return IKS_NOMEM; } if (gnutls_init (&data->sess, GNUTLS_CLIENT) != 0) { gnutls_certificate_free_credentials (data->cred); iks_free (data); return IKS_NOMEM; } gnutls_protocol_set_priority (data->sess, protocol_priority); gnutls_cipher_set_priority(data->sess, cipher_priority); gnutls_compression_set_priority(data->sess, comp_priority); gnutls_kx_set_priority(data->sess, kx_priority); gnutls_mac_set_priority(data->sess, mac_priority); gnutls_credentials_set (data->sess, GNUTLS_CRD_CERTIFICATE, data->cred); gnutls_transport_set_push_function (data->sess, (gnutls_push_func) tls_push); gnutls_transport_set_pull_function (data->sess, (gnutls_pull_func) tls_pull); gnutls_transport_set_ptr (data->sess, data); ret = gnutls_handshake (data->sess); if (ret != 0) { gnutls_deinit (data->sess); gnutls_certificate_free_credentials (data->cred); iks_free (data); return IKS_NET_TLSFAIL; } *datap = data; return IKS_OK; }
int SSL_accept (SSL * ssl) { X509_STORE_CTX *store; int cert_list_size = 0; int err; int i, j; int x_priority[GNUTLS_MAX_ALGORITHM_NUM]; /* take options into account before accepting */ memset (x_priority, 0, sizeof (x_priority)); if (ssl->options & SSL_OP_NO_TLSv1) { for (i = 0, j = 0; i < GNUTLS_MAX_ALGORITHM_NUM && x_priority[i] != 0; i++, j++) { if (ssl->ctx->method->protocol_priority[j] == GNUTLS_TLS1) j++; else x_priority[i] = ssl->ctx->method->protocol_priority[j]; } if (i < GNUTLS_MAX_ALGORITHM_NUM) x_priority[i] = 0; gnutls_protocol_set_priority (ssl->gnutls_state, ssl->ctx->method->protocol_priority); } /* FIXME: dh params, do we want client cert? */ err = gnutls_handshake (ssl->gnutls_state); ssl->last_error = err; if (err < 0) { last_error = err; return 0; } store = (X509_STORE_CTX *) calloc (1, sizeof (X509_STORE_CTX)); store->ssl = ssl; store->cert_list = gnutls_certificate_get_peers (ssl->gnutls_state, &cert_list_size); if (ssl->verify_callback) { ssl->verify_callback (1 /*FIXME*/, store); } ssl->state = SSL_ST_OK; err = store->error; free (store); /* FIXME: deal with error from callback */ return 1; }
static void ADD_PROTOCOL3 (gnutls_session session, int p1, int p2, int p3) { static int _proto_priority[] = { 0, 0, 0, 0 }; _proto_priority[0] = p1; _proto_priority[1] = p2; _proto_priority[2] = p3; gnutls_protocol_set_priority (session, _proto_priority); }
static int tls_gnutls_init_session(struct tls_global *global, struct tls_connection *conn) { #if LIBGNUTLS_VERSION_NUMBER >= 0x020200 const char *err; #else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */ const int cert_types[2] = { GNUTLS_CRT_X509, 0 }; const int protos[2] = { GNUTLS_TLS1, 0 }; #endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */ int ret; ret = gnutls_init(&conn->session, global->server ? GNUTLS_SERVER : GNUTLS_CLIENT); if (ret < 0) { wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS " "connection: %s", gnutls_strerror(ret)); return -1; } ret = gnutls_set_default_priority(conn->session); if (ret < 0) goto fail; #if LIBGNUTLS_VERSION_NUMBER >= 0x020200 ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0", &err); if (ret < 0) { wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at " "'%s'", err); goto fail; } #else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */ ret = gnutls_certificate_type_set_priority(conn->session, cert_types); if (ret < 0) goto fail; ret = gnutls_protocol_set_priority(conn->session, protos); if (ret < 0) goto fail; #endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */ gnutls_transport_set_pull_function(conn->session, tls_pull_func); gnutls_transport_set_push_function(conn->session, tls_push_func); gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn); return 0; fail: wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s", gnutls_strerror(ret)); gnutls_deinit(conn->session); return -1; }
/* initializes a gnutls_session with some defaults. */ static gnutls_session init_tls_session (const char *hostname) { gnutls_session session; gnutls_init (&session, GNUTLS_CLIENT); /* allow the use of private ciphersuites. */ if (disable_extensions == 0) { gnutls_handshake_set_private_extensions (session, 1); gnutls_server_name_set (session, GNUTLS_NAME_DNS, hostname, strlen (hostname)); gnutls_certificate_type_set_priority (session, cert_type_priority); } gnutls_cipher_set_priority (session, cipher_priority); gnutls_compression_set_priority (session, comp_priority); gnutls_kx_set_priority (session, kx_priority); gnutls_protocol_set_priority (session, protocol_priority); gnutls_mac_set_priority (session, mac_priority); gnutls_dh_set_prime_bits (session, 512); gnutls_credentials_set (session, GNUTLS_CRD_ANON, anon_cred); gnutls_credentials_set (session, GNUTLS_CRD_SRP, srp_cred); gnutls_credentials_set (session, GNUTLS_CRD_PSK, psk_cred); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); gnutls_certificate_client_set_retrieve_function (xcred, cert_callback); /* send the fingerprint */ if (fingerprint != 0) gnutls_openpgp_send_key (session, GNUTLS_OPENPGP_KEY_FINGERPRINT); /* use the max record size extension */ if (record_max_size > 0 && disable_extensions == 0) { if (gnutls_record_set_max_size (session, record_max_size) < 0) { fprintf (stderr, "Cannot set the maximum record size to %d.\n", record_max_size); fprintf (stderr, "Possible values: 512, 1024, 2048, 4096.\n"); exit (1); } } return session; }
static int handshake (struct stream_data *data) { const int protocol_priority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 }; const int kx_priority[] = { GNUTLS_KX_RSA, 0 }; const int cipher_priority[] = { GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0}; const int comp_priority[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 }; const int mac_priority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 }; int ret; #ifndef WIN32 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); #endif if (gnutls_global_init () != 0) return IKS_NOMEM; if (gnutls_certificate_allocate_credentials (&data->cred) < 0) return IKS_NOMEM; if (gnutls_init (&data->sess, GNUTLS_CLIENT) != 0) { gnutls_certificate_free_credentials (data->cred); return IKS_NOMEM; } gnutls_protocol_set_priority (data->sess, protocol_priority); gnutls_cipher_set_priority(data->sess, cipher_priority); gnutls_compression_set_priority(data->sess, comp_priority); gnutls_kx_set_priority(data->sess, kx_priority); gnutls_mac_set_priority(data->sess, mac_priority); gnutls_credentials_set (data->sess, GNUTLS_CRD_CERTIFICATE, data->cred); gnutls_transport_set_push_function (data->sess, (gnutls_push_func) tls_push); gnutls_transport_set_pull_function (data->sess, (gnutls_pull_func) tls_pull); gnutls_transport_set_ptr (data->sess, data->prs); ret = gnutls_handshake (data->sess); if (ret != 0) { gnutls_deinit (data->sess); gnutls_certificate_free_credentials (data->cred); return IKS_NET_TLSFAIL; } data->flags &= (~SF_TRY_SECURE); data->flags |= SF_SECURE; iks_send_header (data->prs, data->server); return IKS_OK; } // HAVE_GNUTLS
SSL * SSL_new (SSL_CTX * ctx) { SSL *ssl; int err; ssl = (SSL *) calloc (1, sizeof (SSL)); if (!ssl) return NULL; err = gnutls_certificate_allocate_credentials (&ssl->gnutls_cred); if (err < 0) { last_error = err; free (ssl); return NULL; } gnutls_init (&ssl->gnutls_state, ctx->method->connend); gnutls_protocol_set_priority (ssl->gnutls_state, ctx->method->protocol_priority); gnutls_cipher_set_priority (ssl->gnutls_state, ctx->method->cipher_priority); gnutls_compression_set_priority (ssl->gnutls_state, ctx->method->comp_priority); gnutls_kx_set_priority (ssl->gnutls_state, ctx->method->kx_priority); gnutls_mac_set_priority (ssl->gnutls_state, ctx->method->mac_priority); gnutls_credentials_set (ssl->gnutls_state, GNUTLS_CRD_CERTIFICATE, ssl->gnutls_cred); if (ctx->certfile) gnutls_certificate_set_x509_trust_file (ssl->gnutls_cred, ctx->certfile, ctx->certfile_type); if (ctx->keyfile) gnutls_certificate_set_x509_key_file (ssl->gnutls_cred, ctx->certfile, ctx->keyfile, ctx->keyfile_type); ssl->ctx = ctx; ssl->verify_mode = ctx->verify_mode; ssl->verify_callback = ctx->verify_callback; ssl->options = ctx->options; ssl->rfd = (gnutls_transport_ptr_t) - 1; ssl->wfd = (gnutls_transport_ptr_t) - 1; return ssl; }
static gnutls_session initialize_state(void) { gnutls_session session; gnutls_init(&session, GNUTLS_SERVER); gnutls_protocol_set_priority(session, protocol_priority); gnutls_cipher_set_priority(session, cipher_priority); gnutls_compression_set_priority(session, comp_priority); gnutls_kx_set_priority(session, kx_priority); gnutls_mac_set_priority(session, mac_priority); gnutls_certificate_type_set_priority(session, cert_type_priority); gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred); return session; }
bool GnuTLSClientAnon::init( const std::string&, const std::string&, const StringList& ) { if( m_initLib && gnutls_global_init() != 0 ) return false; if( gnutls_anon_allocate_client_credentials( &m_anoncred ) < 0 ) return false; if( gnutls_init( m_session, GNUTLS_CLIENT ) != 0 ) return false; #if GNUTLS_VERSION_NUMBER >= 0x020600 int ret = gnutls_priority_set_direct( *m_session, "SECURE128:+PFS:+COMP-ALL:+VERS-TLS-ALL:-VERS-SSL3.0:+SIGN-ALL:+CURVE-ALL", 0 ); if( ret != GNUTLS_E_SUCCESS ) return false; #else const int protocolPriority[] = { #ifdef GNUTLS_TLS1_2 GNUTLS_TLS1_2, #endif GNUTLS_TLS1_1, GNUTLS_TLS1, 0 }; const int protocolPriority[] = { GNUTLS_TLS1, 0 }; const int kxPriority[] = { GNUTLS_KX_ANON_DH, 0 }; const int cipherPriority[] = { GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0 }; const int compPriority[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 }; const int macPriority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 }; gnutls_protocol_set_priority( *m_session, protocolPriority ); gnutls_cipher_set_priority( *m_session, cipherPriority ); gnutls_compression_set_priority( *m_session, compPriority ); gnutls_kx_set_priority( *m_session, kxPriority ); gnutls_mac_set_priority( *m_session, macPriority ); #endif gnutls_credentials_set( *m_session, GNUTLS_CRD_ANON, m_anoncred ); gnutls_transport_set_ptr( *m_session, (gnutls_transport_ptr_t)this ); gnutls_transport_set_push_function( *m_session, pushFunc ); gnutls_transport_set_pull_function( *m_session, pullFunc ); m_valid = true; return true; }
bool GnuTLSServerAnon::init( const std::string&, const std::string&, const StringList& ) { const int protocolPriority[] = { GNUTLS_TLS1, 0 }; const int kxPriority[] = { GNUTLS_KX_ANON_DH, 0 }; const int cipherPriority[] = { GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0 }; const int compPriority[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 }; const int macPriority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 }; if( m_initLib && gnutls_global_init() != 0 ) return false; if( gnutls_anon_allocate_server_credentials( &m_anoncred ) < 0 ) return false; generateDH(); gnutls_anon_set_server_dh_params( m_anoncred, m_dhParams ); if( gnutls_init( m_session, GNUTLS_SERVER ) != 0 ) return false; gnutls_protocol_set_priority( *m_session, protocolPriority ); gnutls_cipher_set_priority( *m_session, cipherPriority ); gnutls_compression_set_priority( *m_session, compPriority ); gnutls_kx_set_priority( *m_session, kxPriority ); gnutls_mac_set_priority( *m_session, macPriority ); gnutls_credentials_set( *m_session, GNUTLS_CRD_ANON, m_anoncred ); gnutls_dh_set_prime_bits( *m_session, m_dhBits ); gnutls_transport_set_ptr( *m_session, (gnutls_transport_ptr_t)this ); gnutls_transport_set_push_function( *m_session, pushFunc ); gnutls_transport_set_pull_function( *m_session, pullFunc ); m_valid = true; return true; }
static int tls_gnutls_init_session(struct tls_global *global, struct tls_connection *conn) { const int cert_types[2] = { GNUTLS_CRT_X509, 0 }; const int protos[2] = { GNUTLS_TLS1, 0 }; int ret; ret = gnutls_init(&conn->session, global->server ? GNUTLS_SERVER : GNUTLS_CLIENT); if (ret < 0) { wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS " "connection: %s", gnutls_strerror(ret)); return -1; } ret = gnutls_set_default_priority(conn->session); if (ret < 0) goto fail; ret = gnutls_certificate_type_set_priority(conn->session, cert_types); if (ret < 0) goto fail; ret = gnutls_protocol_set_priority(conn->session, protos); if (ret < 0) goto fail; gnutls_transport_set_pull_function(conn->session, tls_pull_func); gnutls_transport_set_push_function(conn->session, tls_push_func); gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn); return 0; fail: wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s", gnutls_strerror(ret)); gnutls_deinit(conn->session); return -1; }
/** * tls_set_priority - Set the priority of various protocols * @param data TLS socket data * @retval 0 Success * @retval -1 Error */ static int tls_set_priority(struct TlsSockData *data) { size_t nproto = 0; /* number of tls/ssl protocols */ if (C_SslUseTlsv12) protocol_priority[nproto++] = GNUTLS_TLS1_2; if (C_SslUseTlsv11) protocol_priority[nproto++] = GNUTLS_TLS1_1; if (C_SslUseTlsv1) protocol_priority[nproto++] = GNUTLS_TLS1; if (C_SslUseSslv3) protocol_priority[nproto++] = GNUTLS_SSL3; protocol_priority[nproto] = 0; if (nproto == 0) { mutt_error(_("All available protocols for TLS/SSL connection disabled")); return -1; } if (C_SslCiphers) { mutt_error( _("Explicit ciphersuite selection via $ssl_ciphers not supported")); } if (certerr & CERTERR_INSECUREALG) { row++; strfcpy(menu->dialog[row], _("Warning: Server certificate was signed using an insecure algorithm"), dialog_row_len); } /* We use default priorities (see gnutls documentation), * except for protocol version */ gnutls_set_default_priority(data->state); gnutls_protocol_set_priority(data->state, protocol_priority); return 0; }
static struct mailstream_ssl_data * ssl_data_new(int fd, void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data) { struct mailstream_ssl_data * ssl_data; gnutls_session session; struct mailstream_cancel * cancel; const int cipher_prio[] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_ARCFOUR_128, 0 }; const int kx_prio[] = { GNUTLS_KX_DHE_RSA, GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS, 0 }; const int mac_prio[] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 }; const int proto_prio[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 }; gnutls_certificate_credentials_t xcred; int r; struct mailstream_ssl_context * ssl_context = NULL; mailstream_ssl_init(); if (gnutls_certificate_allocate_credentials (&xcred) != 0) return NULL; r = gnutls_init(&session, GNUTLS_CLIENT); if (session == NULL || r != 0) return NULL; if (callback != NULL) { ssl_context = mailstream_ssl_context_new(session, fd); callback(ssl_context, cb_data); } gnutls_session_set_ptr(session, ssl_context); gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred); gnutls_certificate_client_set_retrieve_function(xcred, mailstream_gnutls_client_cert_cb); gnutls_set_default_priority(session); gnutls_protocol_set_priority (session, proto_prio); gnutls_cipher_set_priority (session, cipher_prio); gnutls_kx_set_priority (session, kx_prio); gnutls_mac_set_priority (session, mac_prio); gnutls_record_disable_padding(session); gnutls_dh_set_prime_bits(session, 512); gnutls_transport_set_ptr(session, (gnutls_transport_ptr) fd); /* lower limits on server key length restriction */ gnutls_dh_set_prime_bits(session, 512); do { r = gnutls_handshake(session); } while (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED); if (r < 0) { gnutls_perror(r); goto free_ssl_conn; } cancel = mailstream_cancel_new(); if (cancel == NULL) goto free_ssl_conn; r = mailstream_prepare_fd(fd); if (r < 0) goto free_cancel; ssl_data = malloc(sizeof(* ssl_data)); if (ssl_data == NULL) goto err; ssl_data->fd = fd; ssl_data->session = session; ssl_data->xcred = xcred; ssl_data->cancel = cancel; mailstream_ssl_context_free(ssl_context); return ssl_data; free_cancel: mailstream_cancel_free(cancel); free_ssl_conn: gnutls_certificate_free_credentials(xcred); mailstream_ssl_context_free(ssl_context); gnutls_deinit(session); err: return NULL; }
bool mrutils::TLSServer::use(mrutils::Socket* socket) { const char priorityEncryption[] = "NORMAL:+SRP"; const int priorityProtocols[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 }; int ret; const char * err; //closeSession(); this->socket = socket; reader.use(*socket); mrutils::mutexAcquire(connectionMutex); std::cout << "gnutls_init" << std::endl; gnutls_init (&session, GNUTLS_SERVER); /* Encryption priorities */ std::cout << "gnutls_priority_set_direct" << std::endl; ret = gnutls_priority_set_direct (session, priorityEncryption, &err); if (ret < 0) { if (ret == GNUTLS_E_INVALID_REQUEST) { fprintf (stderr, "Syntax error at: %s\n", err); } mrutils::mutexRelease(connectionMutex); return false; } /* Protocol priorities */ std::cout << "gnutls_protocol_set_priority" << std::endl; ret = gnutls_protocol_set_priority(session, priorityProtocols); if (ret < 0) { printf("unable to set proto priority\n"); mrutils::mutexRelease(connectionMutex); return false; } std::cout << "gnutls_credentials_set" << std::endl; gnutls_credentials_set (session, GNUTLS_CRD_SRP, srp_cred); std::cout << "gnutls_certificate_server_set_request" << std::endl; gnutls_certificate_server_set_request (session, GNUTLS_CERT_IGNORE); std::cout << "gnutls_transport_set_ptr " << socket->s_ << std::endl; gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) socket->s_); init_ = true; /* Perform the TLS handshake */ std::cout << "gnutls_handshake" << std::endl; ret = gnutls_handshake (session); if (ret < 0) { fprintf (stderr, "*** Handshake failed\n"); gnutls_perror (ret); mrutils::mutexRelease(connectionMutex); return false; } if (!reader.open( fastdelegate::MakeDelegate(this ,&TLSServer::recv), (void*) session )) { printf("Unable to open mrutils::BufferedReader"); mrutils::mutexRelease(connectionMutex); return false; } mrutils::mutexRelease(connectionMutex); return (connected_ = true); }
int vnc_tls_client_setup(struct VncState *vs, int needX509Creds) { static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 }; static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0}; static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0}; VNC_DEBUG("Do TLS setup\n"); if (vnc_tls_initialize() < 0) { VNC_DEBUG("Failed to init TLS\n"); vnc_client_error(vs); return -1; } if (vs->tls.session == NULL) { if (gnutls_init(&vs->tls.session, GNUTLS_SERVER) < 0) { vnc_client_error(vs); return -1; } if (gnutls_set_default_priority(vs->tls.session) < 0) { gnutls_deinit(vs->tls.session); vs->tls.session = NULL; vnc_client_error(vs); return -1; } if (gnutls_kx_set_priority(vs->tls.session, needX509Creds ? kx_x509 : kx_anon) < 0) { gnutls_deinit(vs->tls.session); vs->tls.session = NULL; vnc_client_error(vs); return -1; } if (gnutls_certificate_type_set_priority(vs->tls.session, cert_type_priority) < 0) { gnutls_deinit(vs->tls.session); vs->tls.session = NULL; vnc_client_error(vs); return -1; } if (gnutls_protocol_set_priority(vs->tls.session, protocol_priority) < 0) { gnutls_deinit(vs->tls.session); vs->tls.session = NULL; vnc_client_error(vs); return -1; } if (needX509Creds) { gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(vs->vd); if (!x509_cred) { gnutls_deinit(vs->tls.session); vs->tls.session = NULL; vnc_client_error(vs); return -1; } if (gnutls_credentials_set(vs->tls.session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) { gnutls_deinit(vs->tls.session); vs->tls.session = NULL; gnutls_certificate_free_credentials(x509_cred); vnc_client_error(vs); return -1; } if (vs->vd->tls.x509verify) { VNC_DEBUG("Requesting a client certificate\n"); gnutls_certificate_server_set_request (vs->tls.session, GNUTLS_CERT_REQUEST); } } else { gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred(); if (!anon_cred) { gnutls_deinit(vs->tls.session); vs->tls.session = NULL; vnc_client_error(vs); return -1; } if (gnutls_credentials_set(vs->tls.session, GNUTLS_CRD_ANON, anon_cred) < 0) { gnutls_deinit(vs->tls.session); vs->tls.session = NULL; gnutls_anon_free_server_credentials(anon_cred); vnc_client_error(vs); return -1; } } gnutls_transport_set_ptr(vs->tls.session, (gnutls_transport_ptr_t)vs); gnutls_transport_set_push_function(vs->tls.session, vnc_tls_push); gnutls_transport_set_pull_function(vs->tls.session, vnc_tls_pull); } return 0; }
/* tls_negotiate: After TLS state has been initialised, attempt to negotiate * TLS over the wire, including certificate checks. */ static int tls_negotiate (CONNECTION * conn) { tlssockdata *data; int err; size_t nproto = 0; /* number of tls/ssl protocols */ data = (tlssockdata *) safe_calloc (1, sizeof (tlssockdata)); conn->sockdata = data; err = gnutls_certificate_allocate_credentials (&data->xcred); if (err < 0) { FREE(&conn->sockdata); mutt_error ("gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err)); mutt_sleep (2); return -1; } gnutls_certificate_set_x509_trust_file (data->xcred, SslCertFile, GNUTLS_X509_FMT_PEM); /* ignore errors, maybe file doesn't exist yet */ if (SslCACertFile) { gnutls_certificate_set_x509_trust_file (data->xcred, SslCACertFile, GNUTLS_X509_FMT_PEM); } if (SslClientCert) { dprint (2, (debugfile, "Using client certificate %s\n", SslClientCert)); gnutls_certificate_set_x509_key_file (data->xcred, SslClientCert, SslClientCert, GNUTLS_X509_FMT_PEM); } #if HAVE_DECL_GNUTLS_VERIFY_DISABLE_TIME_CHECKS /* disable checking certificate activation/expiration times in gnutls, we do the checks ourselves */ gnutls_certificate_set_verify_flags(data->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS); #endif if ((err = gnutls_init(&data->state, GNUTLS_CLIENT))) { mutt_error ("gnutls_handshake: %s", gnutls_strerror(err)); mutt_sleep (2); goto fail; } /* set socket */ gnutls_transport_set_ptr (data->state, (gnutls_transport_ptr)conn->fd); if (option(OPTTLSV1_2)) protocol_priority[nproto++] = GNUTLS_TLS1_2; if (option(OPTTLSV1_1)) protocol_priority[nproto++] = GNUTLS_TLS1_1; if (option(OPTTLSV1)) protocol_priority[nproto++] = GNUTLS_TLS1; if (option(OPTSSLV3)) protocol_priority[nproto++] = GNUTLS_SSL3; protocol_priority[nproto] = 0; /* disable TLS/SSL protocols as needed */ if (nproto == 0) { mutt_error (_("All available protocols for TLS/SSL connection disabled")); goto fail; } /* else use the list set above */ /* We use default priorities (see gnutls documentation), except for protocol version */ gnutls_set_default_priority (data->state); gnutls_protocol_set_priority (data->state, protocol_priority); if (SslDHPrimeBits > 0) { gnutls_dh_set_prime_bits (data->state, SslDHPrimeBits); } /* gnutls_set_cred (data->state, GNUTLS_ANON, NULL); */ gnutls_credentials_set (data->state, GNUTLS_CRD_CERTIFICATE, data->xcred); err = gnutls_handshake(data->state); while (err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED) { err = gnutls_handshake(data->state); } if (err < 0) { if (err == GNUTLS_E_FATAL_ALERT_RECEIVED) { mutt_error("gnutls_handshake: %s(%s)", gnutls_strerror(err), gnutls_alert_get_name(gnutls_alert_get(data->state))); } else { mutt_error("gnutls_handshake: %s", gnutls_strerror(err)); } mutt_sleep (2); goto fail; } if (!tls_check_certificate(conn)) goto fail; /* set Security Strength Factor (SSF) for SASL */ /* NB: gnutls_cipher_get_key_size() returns key length in bytes */ conn->ssf = gnutls_cipher_get_key_size (gnutls_cipher_get (data->state)) * 8; tls_get_client_cert (conn); if (!option(OPTNOCURSES)) { mutt_message (_("SSL/TLS connection using %s (%s/%s/%s)"), gnutls_protocol_get_name (gnutls_protocol_get_version (data->state)), gnutls_kx_get_name (gnutls_kx_get (data->state)), gnutls_cipher_get_name (gnutls_cipher_get (data->state)), gnutls_mac_get_name (gnutls_mac_get (data->state))); mutt_sleep (0); } return 0; fail: gnutls_certificate_free_credentials (data->xcred); gnutls_deinit (data->state); FREE(&conn->sockdata); return -1; }
static CURLcode gtls_connect_step1(struct connectdata *conn, int sockindex) { #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; #endif struct SessionHandle *data = conn->data; gnutls_session session; int rc; void *ssl_sessionid; size_t ssl_idsize; bool sni = TRUE; /* default is SNI enabled */ #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif if(conn->ssl[sockindex].state == ssl_connection_complete) /* to make us tolerant against being called more than once for the same connection */ return CURLE_OK; if(!gtls_inited) Curl_gtls_init(); /* GnuTLS only supports SSLv3 and TLSv1 */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ /* allocate a cred struct */ rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } #ifdef USE_TLS_SRP if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); rc = gnutls_srp_allocate_client_credentials( &conn->ssl[sockindex].srp_client_cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_srp_allocate_client_cred() failed: %s", gnutls_strerror(rc)); return CURLE_OUT_OF_MEMORY; } rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex]. srp_client_cred, data->set.ssl.username, data->set.ssl.password); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_srp_set_client_cred() failed: %s", gnutls_strerror(rc)); return CURLE_BAD_FUNCTION_ARGUMENT; } } #endif if(data->set.ssl.CAfile) { /* set the trusted CA cert bundle file */ gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred, data->set.ssl.CAfile, GNUTLS_X509_FMT_PEM); if(rc < 0) { infof(data, "error reading ca cert file %s (%s)\n", data->set.ssl.CAfile, gnutls_strerror(rc)); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } else infof(data, "found %d certificates in %s\n", rc, data->set.ssl.CAfile); } if(data->set.ssl.CRLfile) { /* set the CRL list file */ rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred, data->set.ssl.CRLfile, GNUTLS_X509_FMT_PEM); if(rc < 0) { failf(data, "error reading crl file %s (%s)", data->set.ssl.CRLfile, gnutls_strerror(rc)); return CURLE_SSL_CRL_BADFILE; } else infof(data, "found %d CRL in %s\n", rc, data->set.ssl.CRLfile); } /* Initialize TLS session as a client */ rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_init() failed: %d", rc); return CURLE_SSL_CONNECT_ERROR; } /* convenient assign */ session = conn->ssl[sockindex].session; if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && #ifdef ENABLE_IPV6 (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && #endif sni && (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name, strlen(conn->host.name)) < 0)) infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); /* Use default priorities */ rc = gnutls_set_default_priority(session); if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) { #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT static const int protocol_priority[] = { GNUTLS_SSL3, 0 }; rc = gnutls_protocol_set_priority(session, protocol_priority); #else const char *err; /* the combination of the cipher ARCFOUR with SSL 3.0 and TLS 1.0 is not vulnerable to attacks such as the BEAST, why this code now explicitly asks for that */ rc = gnutls_priority_set_direct(session, "NORMAL:-VERS-TLS-ALL:+VERS-SSL3.0:" "-CIPHER-ALL:+ARCFOUR-128", &err); #endif if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; } #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT /* Sets the priority on the certificate types supported by gnutls. Priority is higher for types specified before others. After specifying the types you want, you must append a 0. */ rc = gnutls_certificate_type_set_priority(session, cert_type_priority); if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; #endif if(data->set.str[STRING_CERT]) { if(gnutls_certificate_set_x509_key_file( conn->ssl[sockindex].cred, data->set.str[STRING_CERT], data->set.str[STRING_KEY] ? data->set.str[STRING_KEY] : data->set.str[STRING_CERT], do_file_type(data->set.str[STRING_CERT_TYPE]) ) != GNUTLS_E_SUCCESS) { failf(data, "error reading X.509 key or certificate file"); return CURLE_SSL_CONNECT_ERROR; } } #ifdef USE_TLS_SRP /* put the credentials to the current session */ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, conn->ssl[sockindex].srp_client_cred); if(rc != GNUTLS_E_SUCCESS) failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); } else #endif rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, conn->ssl[sockindex].cred); /* set the connection handle (file descriptor for the socket) */ gnutls_transport_set_ptr(session, GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex])); /* register callback functions to send and receive data. */ gnutls_transport_set_push_function(session, Curl_gtls_push); gnutls_transport_set_pull_function(session, Curl_gtls_pull); /* lowat must be set to zero when using custom push and pull functions. */ gnutls_transport_set_lowat(session, 0); /* This might be a reconnect, so we check for a session ID in the cache to speed up things */ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) { /* we got a session id, use it! */ gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); /* Informational message */ infof (data, "SSL re-using session ID\n"); } return CURLE_OK; }
static gnutls_session tls_session_init(int side, uschar *expciphers, uschar *expmac, uschar *expkx, uschar *expproto) { gnutls_session session; gnutls_init(&session, side); /* Initialize the lists of permitted protocols, key-exchange methods, ciphers, and MACs. */ memcpy(cipher_priority, default_cipher_priority, sizeof(cipher_priority)); memcpy(mac_priority, default_mac_priority, sizeof(mac_priority)); memcpy(kx_priority, default_kx_priority, sizeof(kx_priority)); memcpy(proto_priority, default_proto_priority, sizeof(proto_priority)); /* The names OpenSSL uses in tls_require_ciphers are of the form DES-CBC3-SHA, using hyphen separators. GnuTLS uses underscore separators. So that I can use either form for tls_require_ciphers in my tests, and also for general convenience, we turn hyphens into underscores before scanning the list. */ if (expciphers != NULL) { uschar *s = expciphers; while (*s != 0) { if (*s == '-') *s = '_'; s++; } } if ((expciphers != NULL && !set_priority(cipher_priority, sizeof(cipher_priority)/sizeof(int), expciphers, cipher_index, sizeof(cipher_index)/sizeof(pri_item), US"cipher")) || (expmac != NULL && !set_priority(mac_priority, sizeof(mac_priority)/sizeof(int), expmac, mac_index, sizeof(mac_index)/sizeof(pri_item), US"MAC")) || (expkx != NULL && !set_priority(kx_priority, sizeof(kx_priority)/sizeof(int), expkx, kx_index, sizeof(kx_index)/sizeof(pri_item), US"key-exchange")) || (expproto != NULL && !set_priority(proto_priority, sizeof(proto_priority)/sizeof(int), expproto, proto_index, sizeof(proto_index)/sizeof(pri_item), US"protocol"))) { gnutls_deinit(session); return NULL; } /* Define the various priorities */ gnutls_cipher_set_priority(session, cipher_priority); gnutls_compression_set_priority(session, comp_priority); gnutls_kx_set_priority(session, kx_priority); gnutls_protocol_set_priority(session, proto_priority); gnutls_mac_set_priority(session, mac_priority); gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred); gnutls_dh_set_prime_bits(session, DH_BITS); /* Request or demand a certificate of the peer, as configured. This will happen only in a server. */ if (verify_requirement != VERIFY_NONE) gnutls_certificate_server_set_request(session, (verify_requirement == VERIFY_OPTIONAL)? GNUTLS_CERT_REQUEST : GNUTLS_CERT_REQUIRE); gnutls_db_set_cache_expiration(session, ssl_session_timeout); /* Reduce security in favour of increased compatibility, if the admin decides to make that trade-off. */ if (gnutls_compat_mode) { #if LIBGNUTLS_VERSION_NUMBER >= 0x020104 DEBUG(D_tls) debug_printf("lowering GnuTLS security, compatibility mode\n"); gnutls_session_enable_compatibility_mode(session); #else DEBUG(D_tls) debug_printf("Unable to set gnutls_compat_mode - GnuTLS version too old\n"); #endif } DEBUG(D_tls) debug_printf("initialized GnuTLS session\n"); return session; }
/* initializes a gnutls_session_t with some defaults. */ static gnutls_session_t init_tls_session (const char *hostname) { const char *err; gnutls_session_t session; gnutls_init (&session, GNUTLS_CLIENT); if (gnutls_priority_set_direct (session, info.priorities, &err) < 0) { fprintf (stderr, "Syntax error at: %s\n", err); exit (1); } /* allow the use of private ciphersuites. */ if (disable_extensions == 0) { gnutls_handshake_set_private_extensions (session, 1); gnutls_server_name_set (session, GNUTLS_NAME_DNS, hostname, strlen (hostname)); if (cert_type_priority[0]) gnutls_certificate_type_set_priority (session, cert_type_priority); } if (cipher_priority[0]) gnutls_cipher_set_priority (session, cipher_priority); if (comp_priority[0]) gnutls_compression_set_priority (session, comp_priority); if (kx_priority[0]) gnutls_kx_set_priority (session, kx_priority); if (protocol_priority[0]) gnutls_protocol_set_priority (session, protocol_priority); if (mac_priority[0]) gnutls_mac_set_priority (session, mac_priority); gnutls_dh_set_prime_bits (session, 512); gnutls_credentials_set (session, GNUTLS_CRD_ANON, anon_cred); if (srp_cred) gnutls_credentials_set (session, GNUTLS_CRD_SRP, srp_cred); if (psk_cred) gnutls_credentials_set (session, GNUTLS_CRD_PSK, psk_cred); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); gnutls_certificate_client_set_retrieve_function (xcred, cert_callback); gnutls_certificate_set_verify_function (xcred, cert_verify_callback); gnutls_certificate_set_verify_flags (xcred, 0); /* send the fingerprint */ #ifdef ENABLE_OPENPGP if (fingerprint != 0) gnutls_openpgp_send_cert (session, GNUTLS_OPENPGP_CERT_FINGERPRINT); #endif /* use the max record size extension */ if (record_max_size > 0 && disable_extensions == 0) { if (gnutls_record_set_max_size (session, record_max_size) < 0) { fprintf (stderr, "Cannot set the maximum record size to %d.\n", record_max_size); fprintf (stderr, "Possible values: 512, 1024, 2048, 4096.\n"); exit (1); } } #ifdef ENABLE_OPRFI if (info.opaque_prf_input) gnutls_oprfi_enable_client (session, strlen (info.opaque_prf_input), info.opaque_prf_input); #endif #ifdef ENABLE_SESSION_TICKET if (!info.noticket) gnutls_session_ticket_enable_client (session); #endif return session; }
static CURLcode gtls_connect_step1(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; gnutls_session_t session; int rc; void *ssl_sessionid; size_t ssl_idsize; bool sni = TRUE; /* default is SNI enabled */ #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT static const int cipher_priority[] = { /* These two ciphers were added to GnuTLS as late as ver. 3.0.1, but this code path is only ever used for ver. < 2.12.0. GNUTLS_CIPHER_AES_128_GCM, GNUTLS_CIPHER_AES_256_GCM, */ GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_CAMELLIA_128_CBC, GNUTLS_CIPHER_CAMELLIA_256_CBC, GNUTLS_CIPHER_3DES_CBC, }; static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; static int protocol_priority[] = { 0, 0, 0, 0 }; #else #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509" /* If GnuTLS was compiled without support for SRP it will error out if SRP is requested in the priority string, so treat it specially */ #define GNUTLS_SRP "+SRP" const char* prioritylist; const char *err = NULL; #endif if(conn->ssl[sockindex].state == ssl_connection_complete) /* to make us tolerant against being called more than once for the same connection */ return CURLE_OK; if(!gtls_inited) Curl_gtls_init(); /* GnuTLS only supports SSLv3 and TLSv1 */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ /* allocate a cred struct */ rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } #ifdef USE_TLS_SRP if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); rc = gnutls_srp_allocate_client_credentials( &conn->ssl[sockindex].srp_client_cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_srp_allocate_client_cred() failed: %s", gnutls_strerror(rc)); return CURLE_OUT_OF_MEMORY; } rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex]. srp_client_cred, data->set.ssl.username, data->set.ssl.password); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_srp_set_client_cred() failed: %s", gnutls_strerror(rc)); return CURLE_BAD_FUNCTION_ARGUMENT; } } #endif if(data->set.ssl.CAfile) { /* set the trusted CA cert bundle file */ gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred, data->set.ssl.CAfile, GNUTLS_X509_FMT_PEM); if(rc < 0) { infof(data, "error reading ca cert file %s (%s)\n", data->set.ssl.CAfile, gnutls_strerror(rc)); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } else infof(data, "found %d certificates in %s\n", rc, data->set.ssl.CAfile); } #ifdef HAS_CAPATH if(data->set.ssl.CApath) { /* set the trusted CA cert directory */ rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred, data->set.ssl.CApath, GNUTLS_X509_FMT_PEM); if(rc < 0) { infof(data, "error reading ca cert file %s (%s)\n", data->set.ssl.CAfile, gnutls_strerror(rc)); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } else infof(data, "found %d certificates in %s\n", rc, data->set.ssl.CApath); } #endif #ifdef CURL_CA_FALLBACK /* use system ca certificate store as fallback */ if(data->set.ssl.verifypeer && !(data->set.ssl.CAfile || data->set.ssl.CApath)) { gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred); } #endif if(data->set.ssl.CRLfile) { /* set the CRL list file */ rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred, data->set.ssl.CRLfile, GNUTLS_X509_FMT_PEM); if(rc < 0) { failf(data, "error reading crl file %s (%s)", data->set.ssl.CRLfile, gnutls_strerror(rc)); return CURLE_SSL_CRL_BADFILE; } else infof(data, "found %d CRL in %s\n", rc, data->set.ssl.CRLfile); } /* Initialize TLS session as a client */ rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_init() failed: %d", rc); return CURLE_SSL_CONNECT_ERROR; } /* convenient assign */ session = conn->ssl[sockindex].session; if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && #ifdef ENABLE_IPV6 (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && #endif sni && (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name, strlen(conn->host.name)) < 0)) infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); /* Use default priorities */ rc = gnutls_set_default_priority(session); if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT rc = gnutls_cipher_set_priority(session, cipher_priority); if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; /* Sets the priority on the certificate types supported by gnutls. Priority is higher for types specified before others. After specifying the types you want, you must append a 0. */ rc = gnutls_certificate_type_set_priority(session, cert_type_priority); if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; if(data->set.ssl.cipher_list != NULL) { failf(data, "can't pass a custom cipher list to older GnuTLS" " versions"); return CURLE_SSL_CONNECT_ERROR; } switch (data->set.ssl.version) { case CURL_SSLVERSION_SSLv3: protocol_priority[0] = GNUTLS_SSL3; break; case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: protocol_priority[0] = GNUTLS_TLS1_0; protocol_priority[1] = GNUTLS_TLS1_1; protocol_priority[2] = GNUTLS_TLS1_2; break; case CURL_SSLVERSION_TLSv1_0: protocol_priority[0] = GNUTLS_TLS1_0; break; case CURL_SSLVERSION_TLSv1_1: protocol_priority[0] = GNUTLS_TLS1_1; break; case CURL_SSLVERSION_TLSv1_2: protocol_priority[0] = GNUTLS_TLS1_2; break; case CURL_SSLVERSION_SSLv2: default: failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; break; } rc = gnutls_protocol_set_priority(session, protocol_priority); if(rc != GNUTLS_E_SUCCESS) { failf(data, "Did you pass a valid GnuTLS cipher list?"); return CURLE_SSL_CONNECT_ERROR; } #else /* Ensure +SRP comes at the *end* of all relevant strings so that it can be * removed if a run-time error indicates that SRP is not supported by this * GnuTLS version */ switch (data->set.ssl.version) { case CURL_SSLVERSION_SSLv3: prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0"; sni = false; break; case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP; break; case CURL_SSLVERSION_TLSv1_0: prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" "+VERS-TLS1.0:" GNUTLS_SRP; break; case CURL_SSLVERSION_TLSv1_1: prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" "+VERS-TLS1.1:" GNUTLS_SRP; break; case CURL_SSLVERSION_TLSv1_2: prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" "+VERS-TLS1.2:" GNUTLS_SRP; break; case CURL_SSLVERSION_SSLv2: default: failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; break; } rc = gnutls_priority_set_direct(session, prioritylist, &err); if((rc == GNUTLS_E_INVALID_REQUEST) && err) { if(!strcmp(err, GNUTLS_SRP)) { /* This GnuTLS was probably compiled without support for SRP. * Note that fact and try again without it. */ int validprioritylen = curlx_uztosi(err - prioritylist); char *prioritycopy = strdup(prioritylist); if(!prioritycopy) return CURLE_OUT_OF_MEMORY; infof(data, "This GnuTLS does not support SRP\n"); if(validprioritylen) /* Remove the :+SRP */ prioritycopy[validprioritylen - 1] = 0; rc = gnutls_priority_set_direct(session, prioritycopy, &err); free(prioritycopy); } } if(rc != GNUTLS_E_SUCCESS) { failf(data, "Error %d setting GnuTLS cipher list starting with %s", rc, err); return CURLE_SSL_CONNECT_ERROR; } #endif #ifdef HAS_ALPN if(data->set.ssl_enable_alpn) { int cur = 0; gnutls_datum_t protocols[2]; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) { protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID; protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN; cur++; infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); } #endif protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1; protocols[cur].size = ALPN_HTTP_1_1_LENGTH; cur++; infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); gnutls_alpn_set_protocols(session, protocols, cur, 0); } #endif if(data->set.str[STRING_CERT]) { if(data->set.str[STRING_KEY_PASSWD]) { #if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 const unsigned int supported_key_encryption_algorithms = GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR | GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES | GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 | GNUTLS_PKCS_USE_PBES2_AES_256; rc = gnutls_certificate_set_x509_key_file2( conn->ssl[sockindex].cred, data->set.str[STRING_CERT], data->set.str[STRING_KEY] ? data->set.str[STRING_KEY] : data->set.str[STRING_CERT], do_file_type(data->set.str[STRING_CERT_TYPE]), data->set.str[STRING_KEY_PASSWD], supported_key_encryption_algorithms); if(rc != GNUTLS_E_SUCCESS) { failf(data, "error reading X.509 potentially-encrypted key file: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } #else failf(data, "gnutls lacks support for encrypted key files"); return CURLE_SSL_CONNECT_ERROR; #endif } else { rc = gnutls_certificate_set_x509_key_file( conn->ssl[sockindex].cred, data->set.str[STRING_CERT], data->set.str[STRING_KEY] ? data->set.str[STRING_KEY] : data->set.str[STRING_CERT], do_file_type(data->set.str[STRING_CERT_TYPE]) ); if(rc != GNUTLS_E_SUCCESS) { failf(data, "error reading X.509 key or certificate file: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } } } #ifdef USE_TLS_SRP /* put the credentials to the current session */ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, conn->ssl[sockindex].srp_client_cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } } else #endif { rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, conn->ssl[sockindex].cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } } /* set the connection handle (file descriptor for the socket) */ gnutls_transport_set_ptr(session, GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex])); /* register callback functions to send and receive data. */ gnutls_transport_set_push_function(session, Curl_gtls_push); gnutls_transport_set_pull_function(session, Curl_gtls_pull); /* lowat must be set to zero when using custom push and pull functions. */ gnutls_transport_set_lowat(session, 0); #ifdef HAS_OCSP if(data->set.ssl.verifystatus) { rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc); return CURLE_SSL_CONNECT_ERROR; } } #endif /* This might be a reconnect, so we check for a session ID in the cache to speed up things */ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) { /* we got a session id, use it! */ gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); /* Informational message */ infof (data, "SSL re-using session ID\n"); } return CURLE_OK; }
TLSSession_GnuTLS::TLSSession_GnuTLS(shared_ptr <security::cert::certificateVerifier> cv, shared_ptr <TLSProperties> props) : m_certVerifier(cv), m_props(props) { int res; m_gnutlsSession = new gnutls_session; if (gnutls_init(m_gnutlsSession, GNUTLS_CLIENT) != 0) throw std::bad_alloc(); // Sets some default priority on the ciphers, key exchange methods, // macs and compression methods. #ifdef VMIME_HAVE_GNUTLS_PRIORITY_FUNCS gnutls_dh_set_prime_bits(*m_gnutlsSession, 128); if ((res = gnutls_priority_set_direct (*m_gnutlsSession, m_props->getCipherSuite().c_str(), NULL)) != 0) { throwTLSException("gnutls_priority_set_direct", res); } #else // !VMIME_HAVE_GNUTLS_PRIORITY_FUNCS gnutls_set_default_priority(*m_gnutlsSession); // Sets the priority on the certificate types supported by gnutls. // Priority is higher for types specified before others. After // specifying the types you want, you must append a 0. const int certTypePriority[] = { GNUTLS_CRT_X509, 0 }; res = gnutls_certificate_type_set_priority (*m_gnutlsSession, certTypePriority); if (res < 0) { throwTLSException ("gnutls_certificate_type_set_priority", res); } // Sets the priority on the protocol types const int protoPriority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 }; res = gnutls_protocol_set_priority(*m_gnutlsSession, protoPriority); if (res < 0) { throwTLSException ("gnutls_certificate_type_set_priority", res); } // Priority on the ciphers const int cipherPriority[] = { GNUTLS_CIPHER_ARCFOUR_128, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_ARCFOUR_40, GNUTLS_CIPHER_RC2_40_CBC, GNUTLS_CIPHER_DES_CBC, 0 }; gnutls_cipher_set_priority(*m_gnutlsSession, cipherPriority); // Priority on MACs const int macPriority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0}; gnutls_mac_set_priority(*m_gnutlsSession, macPriority); // Priority on key exchange methods const int kxPriority[] = { GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA, GNUTLS_KX_ANON_DH, GNUTLS_KX_SRP, GNUTLS_KX_RSA_EXPORT, GNUTLS_KX_SRP_RSA, GNUTLS_KX_SRP_DSS, 0 }; gnutls_kx_set_priority(*m_gnutlsSession, kxPriority); // Priority on compression methods const int compressionPriority[] = { GNUTLS_COMP_ZLIB, //GNUTLS_COMP_LZO, GNUTLS_COMP_NULL, 0 }; gnutls_compression_set_priority(*m_gnutlsSession, compressionPriority); #endif // !VMIME_HAVE_GNUTLS_PRIORITY_FUNCS // Initialize credentials gnutls_credentials_set(*m_gnutlsSession, GNUTLS_CRD_ANON, g_gnutlsGlobal.anonCred); gnutls_credentials_set(*m_gnutlsSession, GNUTLS_CRD_CERTIFICATE, g_gnutlsGlobal.certCred); }