void* connection_thread(void* arg) { int sd; gnutls_session_t session; pp_session_t ppsession; int ret; sd = (int)(long)arg; ret = initialize_tls_session(&session); if (ret != GNUTLS_E_SUCCESS) { fprintf(stderr, "Error initializing TLS session\n"); return (void *)(long)ret; } gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)(long)sd); memset(&ppsession, '\0', sizeof(pp_session_t)); ppsession.cfg = &cfg; gnutls_session_set_ptr(session, &ppsession); ret = do_proxy(session); if (ret != GNUTLS_E_SUCCESS) fprintf(stderr, "- Proxy exited with failure\n"); close((int)(long)gnutls_transport_get_ptr(session)); gnutls_deinit(session); return 0; }
static int gnutls_GetFD(vlc_tls_t *tls) { gnutls_session_t session = tls->sys; vlc_tls_t *sock = gnutls_transport_get_ptr(session); return vlc_tls_GetFD(sock); }
static gint ssl_read(gnutls_session_t ssl, gchar *buf, gint len) { gint r; if (gnutls_record_check_pending(ssl) == 0) { if (fd_check_io(GPOINTER_TO_INT(gnutls_transport_get_ptr(ssl)), G_IO_IN) < 0) return -1; } while (1) { r = gnutls_record_recv(ssl, buf, len); if (r > 0) return r; switch (r) { case 0: /* closed connection */ return -1; case GNUTLS_E_REHANDSHAKE: do { r = gnutls_handshake(ssl); } while (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED); break; /* re-receive */ case GNUTLS_E_AGAIN: case GNUTLS_E_INTERRUPTED: errno = EAGAIN; return -1; default: return -1; } } }
test_code_t test_bye (gnutls_session_t session) { int ret; char data[20]; int secs = 6; #ifndef _WIN32 int old; signal (SIGALRM, got_alarm); #endif sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_FAILED) return ret; ret = gnutls_bye (session, GNUTLS_SHUT_WR); if (ret < 0) return TEST_FAILED; #ifndef _WIN32 old = siginterrupt (SIGALRM, 1); alarm (secs); #else setsockopt ((int) gnutls_transport_get_ptr (session), SOL_SOCKET, SO_RCVTIMEO, (char *) &secs, sizeof (int)); #endif do { ret = gnutls_record_recv (session, data, sizeof (data)); } while (ret > 0); #ifndef _WIN32 siginterrupt (SIGALRM, old); #else if (WSAGetLastError () == WSAETIMEDOUT || WSAGetLastError () == WSAECONNABORTED) alrm = 1; #endif if (ret == 0) return TEST_SUCCEED; if (alrm == 0) return TEST_UNSURE; return TEST_FAILED; }
test_code_t test_bye (gnutls_session session) { int ret; char data[20]; int old, secs = 6; #ifndef _WIN32 signal (SIGALRM, got_alarm); #endif ADD_ALL_CIPHERS (session); ADD_ALL_COMP (session); ADD_ALL_CERTTYPES (session); ADD_ALL_PROTOCOLS (session); ADD_ALL_MACS (session); ADD_ALL_KX (session); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_FAILED) return ret; ret = gnutls_bye (session, GNUTLS_SHUT_WR); if (ret < 0) return TEST_FAILED; #ifndef _WIN32 old = siginterrupt (SIGALRM, 1); alarm (secs); #else setsockopt (gnutls_transport_get_ptr (session), SOL_SOCKET, SO_RCVTIMEO, (char *) &secs, sizeof (int)); #endif do { ret = gnutls_record_recv (session, data, sizeof (data)); } while (ret > 0); #ifndef _WIN32 siginterrupt (SIGALRM, old); #else if (WSAGetLastError () == WSAETIMEDOUT || WSAGetLastError () == WSAECONNABORTED) alrm = 1; #endif if (ret == 0) return TEST_SUCCEED; if (alrm == 0) return TEST_UNSURE; return TEST_FAILED; }
static int g_tls_server_connection_gnutls_retrieve_function (gnutls_session_t session, const gnutls_datum_t *req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t *pk_algos, int pk_algos_length, gnutls_retr2_st *st) { g_tls_connection_gnutls_get_certificate (gnutls_transport_get_ptr (session), st); return 0; }
void cib_remote_connection_destroy(gpointer user_data) { crm_client_t *client = user_data; int csock = 0; if (client == NULL) { return; } crm_trace("Cleaning up after client disconnect: %s/%s", crm_str(client->name), client->id); num_clients--; crm_trace("Num unfree'd clients: %d", num_clients); switch (client->kind) { case CRM_CLIENT_TCP: csock = client->remote->tcp_socket; break; #ifdef HAVE_GNUTLS_GNUTLS_H case CRM_CLIENT_TLS: if (client->remote->tls_session) { void *sock_ptr = gnutls_transport_get_ptr(*client->remote->tls_session); csock = GPOINTER_TO_INT(sock_ptr); if (client->remote->tls_handshake_complete) { gnutls_bye(*client->remote->tls_session, GNUTLS_SHUT_WR); } gnutls_deinit(*client->remote->tls_session); gnutls_free(client->remote->tls_session); client->remote->tls_session = NULL; } break; #endif default: crm_warn("Unexpected client type %d", client->kind); } if (csock > 0) { close(csock); } crm_client_destroy(client); crm_trace("Freed the cib client"); if (cib_shutdown_flag) { cib_shutdown(0); } return; }
static gint ssl_write(gnutls_session_t ssl, const gchar *buf, gint len) { gint ret; if (fd_check_io(GPOINTER_TO_INT(gnutls_transport_get_ptr(ssl)), G_IO_OUT) < 0) return -1; ret = gnutls_record_send(ssl, buf, len); switch (ret) { case 0: return -1; case GNUTLS_E_AGAIN: case GNUTLS_E_INTERRUPTED: return 0; default: return ret; } }
static int g_tls_client_connection_gnutls_retrieve_function (gnutls_session_t session, const gnutls_datum_t *req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t *pk_algos, int pk_algos_length, gnutls_retr2_st *st) { GTlsClientConnectionGnutls *gnutls = gnutls_transport_get_ptr (session); GTlsConnectionGnutls *conn = G_TLS_CONNECTION_GNUTLS (gnutls); GPtrArray *accepted_cas; GByteArray *dn; int i; gnutls->priv->cert_requested = TRUE; accepted_cas = g_ptr_array_new_with_free_func ((GDestroyNotify)g_byte_array_unref); for (i = 0; i < nreqs; i++) { dn = g_byte_array_new (); g_byte_array_append (dn, req_ca_rdn[i].data, req_ca_rdn[i].size); g_ptr_array_add (accepted_cas, dn); } if (gnutls->priv->accepted_cas) g_ptr_array_unref (gnutls->priv->accepted_cas); gnutls->priv->accepted_cas = accepted_cas; g_object_notify (G_OBJECT (gnutls), "accepted-cas"); g_tls_connection_gnutls_get_certificate (conn, st); if (st->ncerts == 0) { g_clear_error (&gnutls->priv->cert_error); if (g_tls_connection_gnutls_request_certificate (conn, &gnutls->priv->cert_error)) g_tls_connection_gnutls_get_certificate (conn, st); } return 0; }
static void lrmd_remote_client_destroy(gpointer user_data) { crm_client_t *client = user_data; if (client == NULL) { return; } crm_notice("Cleaning up after remote client %s disconnected " CRM_XS " id=%s", (client->name? client->name : ""), client->id); ipc_proxy_remove_provider(client); /* if this is the last remote connection, stop recurring * operations */ if (crm_hash_table_size(client_connections) == 1) { client_disconnect_cleanup(NULL); } if (client->remote->tls_session) { void *sock_ptr; int csock; sock_ptr = gnutls_transport_get_ptr(*client->remote->tls_session); csock = GPOINTER_TO_INT(sock_ptr); gnutls_bye(*client->remote->tls_session, GNUTLS_SHUT_RDWR); gnutls_deinit(*client->remote->tls_session); gnutls_free(client->remote->tls_session); close(csock); } lrmd_client_destroy(client); return; }
void BIO_get_fd (gnutls_session_t gnutls_state, int *fd) { gnutls_transport_ptr_t tmp = gnutls_transport_get_ptr (gnutls_state); *fd = GNUTLS_POINTER_TO_INT (tmp); }
/*! * \internal * \brief Determine if a remote session has data to read * * \retval 0, timeout occured. * \retval positive, data is ready to be read * \retval negative, session has ended */ int crm_remote_ready(crm_remote_t * remote, int timeout /* ms */ ) { struct pollfd fds = { 0, }; int sock = 0; int rc = 0; time_t start; #ifdef HAVE_GNUTLS_GNUTLS_H if (remote->tls_session) { void *sock_ptr = gnutls_transport_get_ptr(*remote->tls_session); sock = GPOINTER_TO_INT(sock_ptr); } else if (remote->tcp_socket) { #else if (remote->tcp_socket) { #endif sock = remote->tcp_socket; } else { crm_err("Unsupported connection type"); } if (sock <= 0) { crm_trace("No longer connected"); return -ENOTCONN; } start = time(NULL); errno = 0; do { fds.fd = sock; fds.events = POLLIN; /* If we got an EINTR while polling, and we have a * specific timeout we are trying to honor, attempt * to adjust the timeout to the closest second. */ if (errno == EINTR && (timeout > 0)) { timeout = timeout - ((time(NULL) - start) * 1000); if (timeout < 1000) { timeout = 1000; } } rc = poll(&fds, 1, timeout); } while (rc < 0 && errno == EINTR); return rc; } /*! * \internal * \brief Read bytes off non blocking remote connection. * * \note only use with NON-Blocking sockets. Should only be used after polling socket. * This function will return once max_size is met, the socket read buffer * is empty, or an error is encountered. * * \retval number of bytes received */ static size_t crm_remote_recv_once(crm_remote_t * remote) { int rc = 0; size_t read_len = sizeof(struct crm_remote_header_v0); struct crm_remote_header_v0 *header = crm_remote_header(remote); if(header) { /* Stop at the end of the current message */ read_len = header->size_total; } /* automatically grow the buffer when needed */ if(remote->buffer_size < read_len) { remote->buffer_size = 2 * read_len; crm_trace("Expanding buffer to %u bytes", remote->buffer_size); remote->buffer = realloc_safe(remote->buffer, remote->buffer_size + 1); CRM_ASSERT(remote->buffer != NULL); } #ifdef HAVE_GNUTLS_GNUTLS_H if (remote->tls_session) { rc = gnutls_record_recv(*(remote->tls_session), remote->buffer + remote->buffer_offset, remote->buffer_size - remote->buffer_offset); if (rc == GNUTLS_E_INTERRUPTED) { rc = -EINTR; } else if (rc == GNUTLS_E_AGAIN) { rc = -EAGAIN; } else if (rc < 0) { crm_debug("TLS receive failed: %s (%d)", gnutls_strerror(rc), rc); rc = -pcmk_err_generic; } } else if (remote->tcp_socket) { #else if (remote->tcp_socket) { #endif errno = 0; rc = read(remote->tcp_socket, remote->buffer + remote->buffer_offset, remote->buffer_size - remote->buffer_offset); if(rc < 0) { rc = -errno; } } else { crm_err("Unsupported connection type"); return -ESOCKTNOSUPPORT; } /* process any errors. */ if (rc > 0) { remote->buffer_offset += rc; /* always null terminate buffer, the +1 to alloc always allows for this. */ remote->buffer[remote->buffer_offset] = '\0'; crm_trace("Received %u more bytes, %u total", rc, remote->buffer_offset); } else if (rc == -EINTR || rc == -EAGAIN) { crm_trace("non-blocking, exiting read: %s (%d)", pcmk_strerror(rc), rc); } else if (rc == 0) { crm_debug("EOF encoutered after %u bytes", remote->buffer_offset); return -ENOTCONN; } else { crm_debug("Error receiving message after %u bytes: %s (%d)", remote->buffer_offset, pcmk_strerror(rc), rc); return -ENOTCONN; } header = crm_remote_header(remote); if(header) { if(remote->buffer_offset < header->size_total) { crm_trace("Read less than the advertised length: %u < %u bytes", remote->buffer_offset, header->size_total); } else { crm_trace("Read full message of %u bytes", remote->buffer_offset); return remote->buffer_offset; } } return -EAGAIN; } /*! * \internal * \brief Read data off the socket until at least one full message is present or timeout occures. * \retval TRUE message read * \retval FALSE full message not read */ gboolean crm_remote_recv(crm_remote_t * remote, int total_timeout /*ms */ , int *disconnected) { int rc; time_t start = time(NULL); int remaining_timeout = 0; if (total_timeout == 0) { total_timeout = 10000; } else if (total_timeout < 0) { total_timeout = 60000; } *disconnected = 0; remaining_timeout = total_timeout; while ((remaining_timeout > 0) && !(*disconnected)) { /* read some more off the tls buffer if we still have time left. */ crm_trace("waiting to receive remote msg, starting timeout %d, remaining_timeout %d", total_timeout, remaining_timeout); rc = crm_remote_ready(remote, remaining_timeout); if (rc == 0) { crm_err("poll timed out (%d ms) while waiting to receive msg", remaining_timeout); return FALSE; } else if(rc < 0) { crm_debug("poll() failed: %s (%d)", pcmk_strerror(rc), rc); } else { rc = crm_remote_recv_once(remote); if(rc > 0) { return TRUE; } else if (rc < 0) { crm_debug("recv() failed: %s (%d)", pcmk_strerror(rc), rc); } } if(rc == -ENOTCONN) { *disconnected = 1; return FALSE; } remaining_timeout = remaining_timeout - ((time(NULL) - start) * 1000); } return FALSE; }
gnutls_transport_ptr_t session::get_transport_ptr () const { return gnutls_transport_get_ptr (s); }
static void onion_ssl_close(gnutls_session_t s){ int fd=(long int)gnutls_transport_get_ptr(s); gnutls_bye (s, GNUTLS_SHUT_WR); gnutls_deinit (s); onion_close_socket((void*)(long int)fd); }
void BIO_get_fd (gnutls_session_t gnutls_state, int *fd) { *fd = GNUTLS_POINTER_TO_INT (gnutls_transport_get_ptr (gnutls_state)); }
static int tds_verify_certificate(gnutls_session_t session) { unsigned int status; int ret; TDSSOCKET *tds = (TDSSOCKET *) gnutls_transport_get_ptr(session); #ifdef ENABLE_DEVELOPING unsigned int list_size; const gnutls_datum_t *cert_list; #endif if (!tds->login) return GNUTLS_E_CERTIFICATE_ERROR; ret = gnutls_certificate_verify_peers2(session, &status); if (ret < 0) { tdsdump_log(TDS_DBG_ERROR, "Error verifying certificate: %s\n", gnutls_strerror(ret)); return GNUTLS_E_CERTIFICATE_ERROR; } #ifdef ENABLE_DEVELOPING cert_list = gnutls_certificate_get_peers(session, &list_size); if (cert_list) { gnutls_x509_crt_t cert; gnutls_datum_t cinfo; char buf[8192]; size_t size; gnutls_x509_crt_init(&cert); gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); /* This is the preferred way of printing short information about * a certificate. */ size = sizeof(buf); ret = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, buf, &size); if (ret == 0) { FILE *f = fopen("cert.dat", "wb"); if (f) { fwrite(buf, size, 1, f); fclose(f); } } ret = gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_ONELINE, &cinfo); if (ret == 0) { tdsdump_log(TDS_DBG_INFO1, "Certificate info: %s\n", cinfo.data); gnutls_free(cinfo.data); } gnutls_x509_crt_deinit(cert); } #endif /* Certificate is not trusted */ if (status != 0) { tdsdump_log(TDS_DBG_ERROR, "Certificate status: %u\n", status); return GNUTLS_E_CERTIFICATE_ERROR; } /* check hostname */ if (tds->login->check_ssl_hostname) { const gnutls_datum_t *cert_list; unsigned int list_size; gnutls_x509_crt_t cert; cert_list = gnutls_certificate_get_peers(session, &list_size); if (!cert_list) { tdsdump_log(TDS_DBG_ERROR, "Error getting TLS session peers\n"); return GNUTLS_E_CERTIFICATE_ERROR; } gnutls_x509_crt_init(&cert); gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); ret = gnutls_x509_crt_check_hostname(cert, tds_dstr_cstr(&tds->login->server_host_name)); gnutls_x509_crt_deinit(cert); if (!ret) { tdsdump_log(TDS_DBG_ERROR, "Certificate hostname does not match\n"); return GNUTLS_E_CERTIFICATE_ERROR; } } /* notify gnutls to continue handshake normally */ return 0; }
/* This is a send function for the gnutls handshake * protocol. Just makes sure that all data have been sent. */ ssize_t _gnutls_handshake_io_send_int (gnutls_session_t session, content_type_t type, gnutls_handshake_description_t htype, const void *iptr, size_t n) { size_t left; ssize_t ret = 0; const opaque *ptr; ssize_t retval = 0; ptr = iptr; if (session->internals.handshake_send_buffer.length > 0 && ptr == NULL && n == 0) { /* resuming previously interrupted write */ gnutls_assert (); ret = _gnutls_buffer_get (&session->internals.handshake_send_buffer, &ptr, &n); if (ret < 0) { gnutls_assert (); return retval; } type = session->internals.handshake_send_buffer_type; htype = session->internals.handshake_send_buffer_htype; } else if (session->internals.handshake_send_buffer.length > 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } #ifdef WRITE_DEBUG else { size_t sum = 0, x, j; _gnutls_write_log ("HWRITE: will write %d bytes to %d.\n", n, gnutls_transport_get_ptr (session)); for (x = 0; x < ((n) / 16) + 1; x++) { if (sum > n) break; _gnutls_write_log ("%.4x - ", x); for (j = 0; j < 16; j++) { if (sum < n) { _gnutls_write_log ("%.2x ", ((unsigned char *) ptr)[sum++]); } else break; } _gnutls_write_log ("\n"); } _gnutls_write_log ("\n"); } #endif if (n == 0) { /* if we have no data to send */ gnutls_assert (); return 0; } else if (ptr == NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } left = n; while (left > 0) { ret = _gnutls_send_int (session, type, htype, &ptr[n - left], left); if (ret <= 0) { if (ret == 0) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; } if (left > 0 && (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN)) { gnutls_assert (); retval = _gnutls_buffer_insert (&session->internals. handshake_send_buffer, &ptr[n - left], left); if (retval < 0) { gnutls_assert (); return retval; } session->internals.handshake_send_buffer_prev_size += n - left; session->internals.handshake_send_buffer_type = type; session->internals.handshake_send_buffer_htype = htype; } else { session->internals.handshake_send_buffer_prev_size = 0; session->internals.handshake_send_buffer.length = 0; } gnutls_assert (); return ret; } left -= ret; } retval = n + session->internals.handshake_send_buffer_prev_size; session->internals.handshake_send_buffer.length = 0; session->internals.handshake_send_buffer_prev_size = 0; return retval; }