void ssl_init(gnutls_session_t *session, gnutls_certificate_credentials_t *xcred, void *push_cb, void *pull_cb, void *pull_timeout_cb) { /* X509 */ gnutls_certificate_allocate_credentials(xcred); gnutls_certificate_set_verify_function(*xcred, _verify_certificate_callback); /* init things! */ gnutls_init(session, GNUTLS_CLIENT); gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE, *xcred); gnutls_transport_set_push_function(*session, push_cb); gnutls_transport_set_pull_function(*session, pull_cb); gnutls_transport_set_pull_timeout_function(*session, pull_timeout_cb); /* handshake */ gnutls_handshake(*session); }
my_bool ma_ssl_connect(MARIADB_SSL *cssl) { gnutls_session_t ssl = (gnutls_session_t)cssl->ssl; my_bool blocking; MYSQL *mysql; MARIADB_PVIO *pvio; int ret; mysql= (MYSQL *)gnutls_session_get_ptr(ssl); if (!mysql) return 1; pvio= mysql->net.pvio; /* Set socket to blocking if not already set */ if (!(blocking= pvio->methods->is_blocking(pvio))) pvio->methods->blocking(pvio, TRUE, 0); /* we don't use GnuTLS read/write functions */ gnutls_transport_set_ptr(ssl, pvio); gnutls_transport_set_push_function(ssl, ma_ssl_push); gnutls_transport_set_pull_function(ssl, ma_ssl_pull); gnutls_transport_set_pull_timeout_function(ssl, ma_ssl_pull_timeout); gnutls_handshake_set_timeout(ssl, pvio->timeout[PVIO_CONNECT_TIMEOUT]); do { ret = gnutls_handshake(ssl); } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); if (ret < 0) { ma_ssl_set_error(mysql, ret); /* restore blocking mode */ if (!blocking) pvio->methods->blocking(pvio, FALSE, 0); return 1; } cssl->ssl= (void *)ssl; return 0; }
/** * gnutls_transport_set_fastopen: * @session: is a #gnutls_session_t type. * @fd: is the session's socket descriptor * @connect_addr: is the address we want to connect to * @connect_addrlen: is the length of @connect_addr * @flags: must be zero * * Enables TCP Fast Open (TFO) for the specified TLS client session. * That means that TCP connection establishment and the transmission * of the first TLS client hello packet are combined. The * peer's address must be specified in @connect_addr and @connect_addrlen, * and the socket specified by @fd should not be connected. * * TFO only works for TCP sockets of type AF_INET and AF_INET6. * If the OS doesn't support TCP fast open this function will result * to gnutls using connect() transparently during the first write. * * Note: This function overrides all the transport callback functions. * If this is undesirable, TCP Fast Open must be implemented on the user * callback functions without calling this function. When using * this function, transport callbacks must not be set, and * gnutls_transport_set_ptr() or gnutls_transport_set_int() * must not be called. * * On GNU/Linux TFO has to be enabled at the system layer, that is * in /proc/sys/net/ipv4/tcp_fastopen, bit 0 has to be set. * * This function has no effect on server sessions. * * Since: 3.5.3 **/ void gnutls_transport_set_fastopen(gnutls_session_t session, int fd, struct sockaddr *connect_addr, socklen_t connect_addrlen, unsigned int flags) { if (connect_addrlen > (socklen_t)sizeof(session->internals.tfo.connect_addr)) { gnutls_assert(); abort(); } if (session->security_parameters.entity == GNUTLS_SERVER) { gnutls_assert(); return; } memcpy(&session->internals.tfo.connect_addr, connect_addr, connect_addrlen); session->internals.tfo.connect_addrlen = connect_addrlen; session->internals.tfo.fd = fd; gnutls_transport_set_pull_function(session, tfo_read); gnutls_transport_set_pull_timeout_function(session, tfo_recv_timeout); gnutls_transport_set_ptr(session, &session->internals.tfo); session->internals.tfo.flags = 0; #ifdef MSG_NOSIGNAL if (session->internals.flags & GNUTLS_NO_SIGNAL) session->internals.tfo.flags |= MSG_NOSIGNAL; #endif #ifdef _WIN32 gnutls_transport_set_vec_push_function(session, NULL); gnutls_transport_set_push_function(session, tfo_send); #else gnutls_transport_set_vec_push_function(session, tfo_writev); #endif }
struct dtls_gnutls_data *dtls_gnutls_data_create(struct conn *conn,int config) { const char *errpos; int rc; gnutls_datum_t key; int bits; struct dtls_gnutls_data *d = malloc(sizeof(struct dtls_gnutls_data)); if (!d) return 0; gnutls_global_set_log_level(10); gnutls_global_set_log_function(dtls_log_cb); rc = gnutls_init(&d->session, config); if (rc < 0) { cw_log(LOG_ERR, "DTLS - Can't init session: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } gnutls_certificate_allocate_credentials(&d->x509_cred); /* Set credentials */ if (conn->dtls_cert_file && conn->dtls_key_file){ rc = gnutls_certificate_set_x509_key_file(d->x509_cred, conn->dtls_cert_file, conn->dtls_key_file, GNUTLS_X509_FMT_PEM); if (rc < 0) { cw_log(LOG_ERR, "DTLS - Can't set cert/key: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } } /* #if GNUTLS_VERSION_NUMBER >= 0x030100 bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_INSECURE); #else */ bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY); /*#endif*/ /* Set ciphers */ /* rc = gnutls_priority_init(&d->priority_cache, conn->dtls_cipher, &errpos); if (rc < 0) { cw_log(LOG_ERR, "DTLS - Can't init ciphers '%s' at '%s' : %s", conn->dtls_cipher, errpos, gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } rc = gnutls_priority_set(d->session, d->priority_cache); if (rc < 0) { cw_log(LOG_ERR, "DTLS - Can't set priority: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } */ rc = gnutls_priority_set_direct(d->session,conn->dtls_cipher,&errpos); if (rc < 0) { cw_log(LOG_ERR, "DTLS - Can't init ciphers '%s' at '%s' : %s", conn->dtls_cipher, errpos, gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } rc = gnutls_credentials_set(d->session, GNUTLS_CRD_CERTIFICATE, d->x509_cred); if (rc < 0) { cw_log(LOG_ERR, "DTLS - Can't set x.509 credentials: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } gnutls_certificate_set_verify_function(d->x509_cred,verify_cert); gnutls_session_set_ptr(d->session, conn); gnutls_transport_set_ptr(d->session, conn); gnutls_transport_set_pull_function(d->session, dtls_gnutls_bio_read); gnutls_transport_set_push_function(d->session, dtls_gnutls_bio_write); gnutls_transport_set_pull_timeout_function(d->session, dtls_gnutls_bio_wait); #if GNUTLS_VERSION_NUMBER >= 0x030100 gnutls_handshake_set_timeout(d->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); gnutls_dtls_set_data_mtu(d->session, conn->dtls_mtu); #endif gnutls_dtls_set_mtu(d->session, conn->dtls_mtu); return d; }
void doit (void) { /* Server stuff. */ gnutls_anon_server_credentials_t s_anoncred; const gnutls_datum_t p3 = { (void *) pkcs3, strlen (pkcs3) }; static gnutls_dh_params_t dh_params; gnutls_session_t server; int sret, cret; /* Client stuff. */ gnutls_anon_client_credentials_t c_anoncred; gnutls_session_t client; /* Need to enable anonymous KX specifically. */ char buffer[MAX_BUF + 1]; ssize_t ns; int ret, transferred = 0, msglen; /* General init. */ gnutls_global_init (); gnutls_global_set_log_function (tls_log_func); if (debug) gnutls_global_set_log_level (99); /* Init server */ gnutls_anon_allocate_server_credentials (&s_anoncred); gnutls_dh_params_init (&dh_params); gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM); gnutls_anon_set_server_dh_params (s_anoncred, dh_params); gnutls_init (&server, GNUTLS_SERVER|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK); ret = gnutls_priority_set_direct (server, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL); if (ret < 0) exit(1); gnutls_credentials_set (server, GNUTLS_CRD_ANON, s_anoncred); gnutls_dh_set_prime_bits (server, 1024); gnutls_transport_set_push_function (server, server_push); gnutls_transport_set_pull_function (server, server_pull); gnutls_transport_set_pull_timeout_function (server, server_pull_timeout_func); gnutls_transport_set_ptr (server, (gnutls_transport_ptr_t)server); /* Init client */ gnutls_anon_allocate_client_credentials (&c_anoncred); gnutls_init (&client, GNUTLS_CLIENT|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK); cret = gnutls_priority_set_direct (client, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL); if (cret < 0) exit(1); gnutls_credentials_set (client, GNUTLS_CRD_ANON, c_anoncred); gnutls_transport_set_push_function (client, client_push); gnutls_transport_set_pull_function (client, client_pull); gnutls_transport_set_pull_timeout_function (client, client_pull_timeout_func); gnutls_transport_set_ptr (client, (gnutls_transport_ptr_t)client); handshake = 1; HANDSHAKE(client, server); handshake = 0; if (debug) success ("Handshake established\n"); do { ret = gnutls_record_send (client, MSG, strlen (MSG)); } while(ret == GNUTLS_E_AGAIN); //success ("client: sent %d\n", ns); msglen = strlen(MSG); TRANSFER(client, server, MSG, msglen, buffer, MAX_BUF); if (debug) fputs ("\n", stdout); gnutls_bye (client, GNUTLS_SHUT_WR); gnutls_bye (server, GNUTLS_SHUT_WR); gnutls_deinit (client); gnutls_deinit (server); gnutls_anon_free_client_credentials (c_anoncred); gnutls_anon_free_server_credentials (s_anoncred); gnutls_dh_params_deinit (dh_params); gnutls_global_deinit (); }
void udp_server(const char* name, int port, int mtu) { int sock, ret; struct sockaddr_in cli_addr; socklen_t cli_addr_size; char buffer[MAX_BUFFER]; priv_data_st priv; gnutls_session_t session; gnutls_datum_t cookie_key; gnutls_dtls_prestate_st prestate; unsigned char sequence[8]; ret = gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE); if (ret < 0) { fprintf(stderr, "Cannot generate key\n"); exit(1); } ret = listen_socket (name, port, SOCK_DGRAM); if (ret < 0) { fprintf(stderr, "Cannot listen\n"); exit (1); } for (;;) { printf("Waiting for connection...\n"); sock = wait_for_connection(); if (sock < 0) continue; cli_addr_size = sizeof(cli_addr); ret = recvfrom(sock, buffer, sizeof(buffer), MSG_PEEK, (struct sockaddr*)&cli_addr, &cli_addr_size); if (ret > 0) { memset(&prestate, 0, sizeof(prestate)); ret = gnutls_dtls_cookie_verify(&cookie_key, &cli_addr, sizeof(cli_addr), buffer, ret, &prestate); if (ret < 0) /* cookie not valid */ { priv_data_st s; memset(&s,0,sizeof(s)); s.fd = sock; s.cli_addr = (void*)&cli_addr; s.cli_addr_size = sizeof(cli_addr); printf("Sending hello verify request to %s\n", human_addr ((struct sockaddr *) &cli_addr, sizeof(cli_addr), buffer, sizeof(buffer))); gnutls_dtls_cookie_send(&cookie_key, &cli_addr, sizeof(cli_addr), &prestate, (gnutls_transport_ptr_t)&s, push_func); /* discard peeked data*/ recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&cli_addr, &cli_addr_size); continue; } printf ("Accepted connection from %s\n", human_addr ((struct sockaddr *) &cli_addr, sizeof(cli_addr), buffer, sizeof (buffer))); } else continue; session = initialize_session(1); gnutls_dtls_prestate_set(session, &prestate); if (mtu) gnutls_dtls_set_mtu(session, mtu); priv.session = session; priv.fd = sock; priv.cli_addr = (struct sockaddr *)&cli_addr; priv.cli_addr_size = sizeof(cli_addr); gnutls_transport_set_ptr (session, &priv); gnutls_transport_set_push_function (session, push_func); gnutls_transport_set_pull_function (session, pull_func); gnutls_transport_set_pull_timeout_function (session, pull_timeout_func); do { ret = gnutls_handshake(session); } while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); if (ret < 0) { fprintf(stderr, "Error in handshake(): %s\n", gnutls_strerror(ret)); gnutls_deinit(session); continue; } for(;;) { do { ret = gnutls_record_recv_seq(session, buffer, MAX_BUFFER, sequence); } while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); if (ret == GNUTLS_E_REHANDSHAKE) { fprintf (stderr, "*** Received hello message\n"); do { ret = gnutls_handshake (session); } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); if (ret == 0) continue; } if (ret < 0) { fprintf(stderr, "Error in recv(): %s\n", gnutls_strerror(ret)); break; } if (ret == 0) { printf("EOF\n\n"); break; } buffer[ret] = 0; printf("received[%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x]: %s\n", sequence[0], sequence[1], sequence[2], sequence[3], sequence[4], sequence[5], sequence[6], sequence[7], buffer); if (check_command(session, buffer) == 0) { /* reply back */ ret = gnutls_record_send(session, buffer, ret); if (ret < 0) { fprintf(stderr, "Error in send(): %s\n", gnutls_strerror(ret)); break; } } } } gnutls_deinit(session); }
/** * gnutls_init: * @session: is a pointer to a #gnutls_session_t structure. * @flags: indicate if this session is to be used for server or client. * * This function initializes the current session to null. Every * session must be initialized before use, so internal structures can * be allocated. This function allocates structures which can only * be free'd by calling gnutls_deinit(). Returns %GNUTLS_E_SUCCESS (0) on success. * * @flags can be one of %GNUTLS_CLIENT and %GNUTLS_SERVER. For a DTLS * entity, the flags %GNUTLS_DATAGRAM and %GNUTLS_NONBLOCK are * also available. The latter flag will enable a non-blocking * operation of the DTLS timers. * * The flag %GNUTLS_NO_REPLAY_PROTECTION will disable any * replay protection in DTLS mode. That must only used when * replay protection is achieved using other means. * * Note that since version 3.1.2 this function enables some common * TLS extensions such as session tickets and OCSP certificate status * request in client side by default. To prevent that use the %GNUTLS_NO_EXTENSIONS * flag. * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. **/ int gnutls_init(gnutls_session_t * session, unsigned int flags) { int ret; record_parameters_st *epoch; FAIL_IF_LIB_ERROR; *session = gnutls_calloc(1, sizeof(struct gnutls_session_int)); if (*session == NULL) return GNUTLS_E_MEMORY_ERROR; ret = _gnutls_epoch_alloc(*session, 0, &epoch); if (ret < 0) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } /* Set all NULL algos on epoch 0 */ _gnutls_epoch_set_null_algos(*session, epoch); (*session)->security_parameters.epoch_next = 1; (*session)->security_parameters.entity = (flags & GNUTLS_SERVER ? GNUTLS_SERVER : GNUTLS_CLIENT); /* the default certificate type for TLS */ (*session)->security_parameters.cert_type = DEFAULT_CERT_TYPE; /* Initialize buffers */ _gnutls_buffer_init(&(*session)->internals.handshake_hash_buffer); _gnutls_buffer_init(&(*session)->internals.hb_remote_data); _gnutls_buffer_init(&(*session)->internals.hb_local_data); _gnutls_buffer_init(&(*session)->internals.record_presend_buffer); _mbuffer_head_init(&(*session)->internals.record_buffer); _mbuffer_head_init(&(*session)->internals.record_send_buffer); _mbuffer_head_init(&(*session)->internals.record_recv_buffer); _mbuffer_head_init(&(*session)->internals.handshake_send_buffer); _gnutls_handshake_recv_buffer_init(*session); (*session)->internals.expire_time = DEFAULT_EXPIRE_TIME; /* one hour default */ gnutls_handshake_set_max_packet_length((*session), MAX_HANDSHAKE_PACKET_SIZE); /* set the socket pointers to -1; */ (*session)->internals.transport_recv_ptr = (gnutls_transport_ptr_t) - 1; (*session)->internals.transport_send_ptr = (gnutls_transport_ptr_t) - 1; /* set the default maximum record size for TLS */ (*session)->security_parameters.max_record_recv_size = DEFAULT_MAX_RECORD_SIZE; (*session)->security_parameters.max_record_send_size = DEFAULT_MAX_RECORD_SIZE; /* everything else not initialized here is initialized * as NULL or 0. This is why calloc is used. */ _gnutls_handshake_internal_state_init(*session); /* emulate old gnutls behavior for old applications that do not use the priority_* * functions. */ (*session)->internals.priorities.sr = SR_PARTIAL; #ifdef HAVE_WRITEV gnutls_transport_set_vec_push_function(*session, system_writev); #else gnutls_transport_set_push_function(*session, system_write); #endif gnutls_transport_set_pull_function(*session, system_read); gnutls_transport_set_errno_function(*session, system_errno); gnutls_transport_set_pull_timeout_function(*session, system_recv_timeout); (*session)->internals.hb_retrans_timeout_ms = 1000; (*session)->internals.hb_total_timeout_ms = 60000; if (flags & GNUTLS_DATAGRAM) { (*session)->internals.dtls.mtu = DTLS_DEFAULT_MTU; (*session)->internals.transport = GNUTLS_DGRAM; (*session)->internals.dtls.retrans_timeout_ms = 1000; (*session)->internals.dtls.total_timeout_ms = 60000; } else (*session)->internals.transport = GNUTLS_STREAM; if (flags & GNUTLS_NONBLOCK) (*session)->internals.dtls.blocking = 0; else (*session)->internals.dtls.blocking = 1; /* Enable useful extensions */ if ((flags & GNUTLS_CLIENT) && !(flags & GNUTLS_NO_EXTENSIONS)) { #ifdef ENABLE_SESSION_TICKETS gnutls_session_ticket_enable_client(*session); #endif #ifdef ENABLE_OCSP gnutls_ocsp_status_request_enable_client(*session, NULL, 0, NULL); #endif } if (flags & GNUTLS_NO_REPLAY_PROTECTION) (*session)->internals.no_replay_protection = 1; return 0; }
int main (void) { int listen_sd; int sock, ret; struct sockaddr_in sa_serv; struct sockaddr_in cli_addr; socklen_t cli_addr_size; gnutls_session_t session; char buffer[MAX_BUFFER]; priv_data_st priv; gnutls_datum_t cookie_key; gnutls_dtls_prestate_st prestate; int mtu = 1400; unsigned char sequence[8]; /* this must be called once in the program */ gnutls_global_init (); gnutls_certificate_allocate_credentials (&x509_cred); gnutls_certificate_set_x509_trust_file (x509_cred, CAFILE, GNUTLS_X509_FMT_PEM); gnutls_certificate_set_x509_crl_file (x509_cred, CRLFILE, GNUTLS_X509_FMT_PEM); ret = gnutls_certificate_set_x509_key_file (x509_cred, CERTFILE, KEYFILE, GNUTLS_X509_FMT_PEM); if (ret < 0) { printf("No certificate or key were found\n"); exit(1); } generate_dh_params (); gnutls_certificate_set_dh_params (x509_cred, dh_params); gnutls_priority_init (&priority_cache, "PERFORMANCE:-VERS-TLS-ALL:+VERS-DTLS1.0:%SERVER_PRECEDENCE", NULL); gnutls_key_generate (&cookie_key, GNUTLS_COOKIE_KEY_SIZE); /* Socket operations */ listen_sd = socket (AF_INET, SOCK_DGRAM, 0); memset (&sa_serv, '\0', sizeof (sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.s_addr = INADDR_ANY; sa_serv.sin_port = htons (PORT); { /* DTLS requires the IP don't fragment (DF) bit to be set */ #if defined(IP_DONTFRAG) int optval = 1; setsockopt (listen_sd, IPPROTO_IP, IP_DONTFRAG, (const void *) &optval, sizeof (optval)); #elif defined(IP_MTU_DISCOVER) int optval = IP_PMTUDISC_DO; setsockopt(listen_sd, IPPROTO_IP, IP_MTU_DISCOVER, (const void*) &optval, sizeof (optval)); #endif } bind (listen_sd, (struct sockaddr *) &sa_serv, sizeof (sa_serv)); printf ("UDP server ready. Listening to port '%d'.\n\n", PORT); for (;;) { printf ("Waiting for connection...\n"); sock = wait_for_connection (listen_sd); if (sock < 0) continue; cli_addr_size = sizeof (cli_addr); ret = recvfrom (sock, buffer, sizeof (buffer), MSG_PEEK, (struct sockaddr *) &cli_addr, &cli_addr_size); if (ret > 0) { memset (&prestate, 0, sizeof (prestate)); ret = gnutls_dtls_cookie_verify (&cookie_key, &cli_addr, sizeof (cli_addr), buffer, ret, &prestate); if (ret < 0) /* cookie not valid */ { priv_data_st s; memset (&s, 0, sizeof (s)); s.fd = sock; s.cli_addr = (void *) &cli_addr; s.cli_addr_size = sizeof (cli_addr); printf ("Sending hello verify request to %s\n", human_addr ((struct sockaddr *) &cli_addr, sizeof (cli_addr), buffer, sizeof (buffer))); gnutls_dtls_cookie_send (&cookie_key, &cli_addr, sizeof (cli_addr), &prestate, (gnutls_transport_ptr_t) & s, push_func); /* discard peeked data */ recvfrom (sock, buffer, sizeof (buffer), 0, (struct sockaddr *) &cli_addr, &cli_addr_size); usleep (100); continue; } printf ("Accepted connection from %s\n", human_addr ((struct sockaddr *) &cli_addr, sizeof (cli_addr), buffer, sizeof (buffer))); } else continue; session = initialize_tls_session (); gnutls_dtls_prestate_set (session, &prestate); gnutls_dtls_set_mtu (session, mtu); priv.session = session; priv.fd = sock; priv.cli_addr = (struct sockaddr *) &cli_addr; priv.cli_addr_size = sizeof (cli_addr); gnutls_transport_set_ptr (session, &priv); gnutls_transport_set_push_function (session, push_func); gnutls_transport_set_pull_function (session, pull_func); gnutls_transport_set_pull_timeout_function (session, pull_timeout_func); do { ret = gnutls_handshake (session); } while (ret < 0 && gnutls_error_is_fatal (ret) == 0); if (ret < 0) { fprintf (stderr, "Error in handshake(): %s\n", gnutls_strerror (ret)); gnutls_deinit (session); continue; } printf ("- Handshake was completed\n"); for (;;) { do { ret = gnutls_record_recv_seq (session, buffer, MAX_BUFFER, sequence); } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); if (ret < 0) { fprintf (stderr, "Error in recv(): %s\n", gnutls_strerror (ret)); break; } if (ret == 0) { printf ("EOF\n\n"); break; } buffer[ret] = 0; printf ("received[%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x]: %s\n", sequence[0], sequence[1], sequence[2], sequence[3], sequence[4], sequence[5], sequence[6], sequence[7], buffer); /* reply back */ ret = gnutls_record_send (session, buffer, ret); if (ret < 0) { fprintf (stderr, "Error in send(): %s\n", gnutls_strerror (ret)); break; } } gnutls_bye (session, GNUTLS_SHUT_WR); gnutls_deinit (session); } close (listen_sd); gnutls_certificate_free_credentials (x509_cred); gnutls_priority_deinit (priority_cache); gnutls_global_deinit (); return 0; }
void doit(void) { global_init(); int ret; char buf[1024]; /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; /* General init. */ gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(6); /* Init server */ gnutls_certificate_allocate_credentials(&serverx509cred); gnutls_certificate_set_x509_key_mem(serverx509cred, &server2_cert, &server2_key, GNUTLS_X509_FMT_PEM); gnutls_init(&server, GNUTLS_SERVER); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); gnutls_priority_set_direct(server, "NORMAL", NULL); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_pull_timeout_function(server, server_pull_timeout_func); gnutls_transport_set_ptr(server, server); /* Init client */ ret = gnutls_certificate_allocate_credentials(&clientx509cred); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca2_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) exit(1); ret = gnutls_init(&client, GNUTLS_CLIENT); if (ret < 0) exit(1); ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); if (ret < 0) exit(1); ret = gnutls_priority_set_direct(client, "NORMAL", NULL); if (ret < 0) exit(1); gnutls_record_set_max_size(client, 512); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_pull_timeout_function(client, client_pull_timeout_func); gnutls_transport_set_ptr(client, client); HANDSHAKE(client, server); memset(buf, 1, sizeof(buf)); ret = gnutls_record_send(server, buf, 513); if (ret != 512 || ret < 0) { gnutls_perror(ret); exit(1); } success("did not send a 513-byte packet\n"); ret = gnutls_record_send(server, buf, 512); if (ret < 0) { gnutls_perror(ret); exit(1); } success("did send a 512-byte packet\n"); gnutls_bye(client, GNUTLS_SHUT_RDWR); gnutls_bye(server, GNUTLS_SHUT_RDWR); gnutls_deinit(client); gnutls_deinit(server); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); gnutls_global_deinit(); }
/** * gnutls_init: * @session: is a pointer to a #gnutls_session_t structure. * @flags: indicate if this session is to be used for server or client. * * This function initializes the current session to null. Every * session must be initialized before use, so internal structures can * be allocated. This function allocates structures which can only * be free'd by calling gnutls_deinit(). Returns zero on success. * * @flags can be one of %GNUTLS_CLIENT and %GNUTLS_SERVER. For a DTLS * entity, the flags %GNUTLS_DATAGRAM and %GNUTLS_NONBLOCK are * also available. The latter flag will enable a non-blocking * operation of the DTLS timers. * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. **/ int gnutls_init (gnutls_session_t * session, unsigned int flags) { int ret; record_parameters_st *epoch; *session = gnutls_calloc (1, sizeof (struct gnutls_session_int)); if (*session == NULL) return GNUTLS_E_MEMORY_ERROR; ret = _gnutls_epoch_alloc (*session, 0, &epoch); if (ret < 0) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* Set all NULL algos on epoch 0 */ _gnutls_epoch_set_null_algos (*session, epoch); (*session)->security_parameters.epoch_next = 1; (*session)->security_parameters.entity = (flags&GNUTLS_SERVER?GNUTLS_SERVER:GNUTLS_CLIENT); /* the default certificate type for TLS */ (*session)->security_parameters.cert_type = DEFAULT_CERT_TYPE; /* Initialize buffers */ _gnutls_buffer_init (&(*session)->internals.handshake_hash_buffer); _mbuffer_head_init (&(*session)->internals.record_buffer); _mbuffer_head_init (&(*session)->internals.record_send_buffer); _mbuffer_head_init (&(*session)->internals.record_recv_buffer); _mbuffer_head_init (&(*session)->internals.handshake_send_buffer); _gnutls_handshake_recv_buffer_init(*session); (*session)->key = gnutls_calloc (1, sizeof (struct gnutls_key_st)); if ((*session)->key == NULL) { gnutls_free (*session); *session = NULL; return GNUTLS_E_MEMORY_ERROR; } (*session)->internals.expire_time = DEFAULT_EXPIRE_TIME; /* one hour default */ gnutls_dh_set_prime_bits ((*session), MIN_DH_BITS); gnutls_handshake_set_max_packet_length ((*session), MAX_HANDSHAKE_PACKET_SIZE); /* set the socket pointers to -1; */ (*session)->internals.transport_recv_ptr = (gnutls_transport_ptr_t) - 1; (*session)->internals.transport_send_ptr = (gnutls_transport_ptr_t) - 1; /* set the default maximum record size for TLS */ (*session)->security_parameters.max_record_recv_size = DEFAULT_MAX_RECORD_SIZE; (*session)->security_parameters.max_record_send_size = DEFAULT_MAX_RECORD_SIZE; /* everything else not initialized here is initialized * as NULL or 0. This is why calloc is used. */ _gnutls_handshake_internal_state_init (*session); /* emulate old gnutls behavior for old applications that do not use the priority_* * functions. */ (*session)->internals.priorities.sr = SR_PARTIAL; #ifdef HAVE_WRITEV gnutls_transport_set_vec_push_function (*session, system_writev); #else gnutls_transport_set_push_function (*session, system_write); #endif gnutls_transport_set_pull_function (*session, system_read); gnutls_transport_set_errno_function (*session, system_errno); gnutls_transport_set_pull_timeout_function (*session, system_recv_timeout); if (flags & GNUTLS_DATAGRAM) { (*session)->internals.dtls.mtu = DTLS_DEFAULT_MTU; (*session)->internals.transport = GNUTLS_DGRAM; (*session)->internals.dtls.retrans_timeout = 1000; (*session)->internals.dtls.total_timeout = 60000; (*session)->internals.dtls.record_sw_size = 0; } else (*session)->internals.transport = GNUTLS_STREAM; if (flags & GNUTLS_NONBLOCK) (*session)->internals.dtls.blocking = 0; else (*session)->internals.dtls.blocking = 1; return 0; }
int /* O - 0 on success, -1 on failure */ _httpTLSStart(http_t *http) /* I - Connection to server */ { char hostname[256], /* Hostname */ *hostptr; /* Pointer into hostname */ int status; /* Status of handshake */ gnutls_certificate_credentials_t *credentials; /* TLS credentials */ char priority_string[1024]; /* Priority string */ DEBUG_printf(("3_httpTLSStart(http=%p)", http)); if (tls_options < 0) { DEBUG_puts("4_httpTLSStart: Setting defaults."); _cupsSetDefaults(); DEBUG_printf(("4_httpTLSStart: tls_options=%x", tls_options)); } if (http->mode == _HTTP_MODE_SERVER && !tls_keypath) { DEBUG_puts("4_httpTLSStart: cupsSetServerCredentials not called."); http->error = errno = EINVAL; http->status = HTTP_STATUS_ERROR; _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Server credentials not set."), 1); return (-1); } credentials = (gnutls_certificate_credentials_t *) malloc(sizeof(gnutls_certificate_credentials_t)); if (credentials == NULL) { DEBUG_printf(("8_httpStartTLS: Unable to allocate credentials: %s", strerror(errno))); http->error = errno; http->status = HTTP_STATUS_ERROR; _cupsSetHTTPError(HTTP_STATUS_ERROR); return (-1); } gnutls_certificate_allocate_credentials(credentials); status = gnutls_init(&http->tls, http->mode == _HTTP_MODE_CLIENT ? GNUTLS_CLIENT : GNUTLS_SERVER); if (!status) status = gnutls_set_default_priority(http->tls); if (status) { http->error = EIO; http->status = HTTP_STATUS_ERROR; DEBUG_printf(("4_httpTLSStart: Unable to initialize common TLS parameters: %s", gnutls_strerror(status))); _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0); gnutls_deinit(http->tls); gnutls_certificate_free_credentials(*credentials); free(credentials); http->tls = NULL; return (-1); } if (http->mode == _HTTP_MODE_CLIENT) { /* * Client: get the hostname to use for TLS... */ if (httpAddrLocalhost(http->hostaddr)) { strlcpy(hostname, "localhost", sizeof(hostname)); } else { /* * Otherwise make sure the hostname we have does not end in a trailing dot. */ strlcpy(hostname, http->hostname, sizeof(hostname)); if ((hostptr = hostname + strlen(hostname) - 1) >= hostname && *hostptr == '.') *hostptr = '\0'; } status = gnutls_server_name_set(http->tls, GNUTLS_NAME_DNS, hostname, strlen(hostname)); } else { /* * Server: get certificate and private key... */ char crtfile[1024], /* Certificate file */ keyfile[1024]; /* Private key file */ int have_creds = 0; /* Have credentials? */ if (http->fields[HTTP_FIELD_HOST][0]) { /* * Use hostname for TLS upgrade... */ strlcpy(hostname, http->fields[HTTP_FIELD_HOST], sizeof(hostname)); } else { /* * Resolve hostname from connection address... */ http_addr_t addr; /* Connection address */ socklen_t addrlen; /* Length of address */ addrlen = sizeof(addr); if (getsockname(http->fd, (struct sockaddr *)&addr, &addrlen)) { DEBUG_printf(("4_httpTLSStart: Unable to get socket address: %s", strerror(errno))); hostname[0] = '\0'; } else if (httpAddrLocalhost(&addr)) hostname[0] = '\0'; else { httpAddrLookup(&addr, hostname, sizeof(hostname)); DEBUG_printf(("4_httpTLSStart: Resolved socket address to \"%s\".", hostname)); } } if (isdigit(hostname[0] & 255) || hostname[0] == '[') hostname[0] = '\0'; /* Don't allow numeric addresses */ if (hostname[0]) { http_gnutls_make_path(crtfile, sizeof(crtfile), tls_keypath, hostname, "crt"); http_gnutls_make_path(keyfile, sizeof(keyfile), tls_keypath, hostname, "key"); have_creds = !access(crtfile, 0) && !access(keyfile, 0); } else if (tls_common_name) { http_gnutls_make_path(crtfile, sizeof(crtfile), tls_keypath, tls_common_name, "crt"); http_gnutls_make_path(keyfile, sizeof(keyfile), tls_keypath, tls_common_name, "key"); have_creds = !access(crtfile, 0) && !access(keyfile, 0); } if (!have_creds && tls_auto_create && (hostname[0] || tls_common_name)) { DEBUG_printf(("4_httpTLSStart: Auto-create credentials for \"%s\".", hostname[0] ? hostname : tls_common_name)); if (!cupsMakeServerCredentials(tls_keypath, hostname[0] ? hostname : tls_common_name, 0, NULL, time(NULL) + 365 * 86400)) { DEBUG_puts("4_httpTLSStart: cupsMakeServerCredentials failed."); http->error = errno = EINVAL; http->status = HTTP_STATUS_ERROR; _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1); return (-1); } } DEBUG_printf(("4_httpTLSStart: Using certificate \"%s\" and private key \"%s\".", crtfile, keyfile)); status = gnutls_certificate_set_x509_key_file(*credentials, crtfile, keyfile, GNUTLS_X509_FMT_PEM); } if (!status) status = gnutls_credentials_set(http->tls, GNUTLS_CRD_CERTIFICATE, *credentials); if (status) { http->error = EIO; http->status = HTTP_STATUS_ERROR; DEBUG_printf(("4_httpTLSStart: Unable to complete client/server setup: %s", gnutls_strerror(status))); _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0); gnutls_deinit(http->tls); gnutls_certificate_free_credentials(*credentials); free(credentials); http->tls = NULL; return (-1); } strlcpy(priority_string, "NORMAL", sizeof(priority_string)); if (tls_options & _HTTP_TLS_DENY_TLS10) strlcat(priority_string, ":+VERS-TLS-ALL:-VERS-TLS1.0:-VERS-SSL3.0", sizeof(priority_string)); else if (tls_options & _HTTP_TLS_ALLOW_SSL3) strlcat(priority_string, ":+VERS-TLS-ALL", sizeof(priority_string)); else strlcat(priority_string, ":+VERS-TLS-ALL:-VERS-SSL3.0", sizeof(priority_string)); if (!(tls_options & _HTTP_TLS_ALLOW_RC4)) strlcat(priority_string, ":-ARCFOUR-128", sizeof(priority_string)); if (!(tls_options & _HTTP_TLS_ALLOW_DH)) strlcat(priority_string, ":!ANON-DH", sizeof(priority_string)); #ifdef HAVE_GNUTLS_PRIORITY_SET_DIRECT gnutls_priority_set_direct(http->tls, priority_string, NULL); #else gnutls_priority_t priority; /* Priority */ gnutls_priority_init(&priority, priority_string, NULL); gnutls_priority_set(http->tls, priority); gnutls_priority_deinit(priority); #endif /* HAVE_GNUTLS_PRIORITY_SET_DIRECT */ gnutls_transport_set_ptr(http->tls, (gnutls_transport_ptr_t)http); gnutls_transport_set_pull_function(http->tls, http_gnutls_read); #ifdef HAVE_GNUTLS_TRANSPORT_SET_PULL_TIMEOUT_FUNCTION gnutls_transport_set_pull_timeout_function(http->tls, (gnutls_pull_timeout_func)httpWait); #endif /* HAVE_GNUTLS_TRANSPORT_SET_PULL_TIMEOUT_FUNCTION */ gnutls_transport_set_push_function(http->tls, http_gnutls_write); while ((status = gnutls_handshake(http->tls)) != GNUTLS_E_SUCCESS) { DEBUG_printf(("5_httpStartTLS: gnutls_handshake returned %d (%s)", status, gnutls_strerror(status))); if (gnutls_error_is_fatal(status)) { http->error = EIO; http->status = HTTP_STATUS_ERROR; _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0); gnutls_deinit(http->tls); gnutls_certificate_free_credentials(*credentials); free(credentials); http->tls = NULL; return (-1); } } http->tls_credentials = credentials; return (0); }
static int setup_dtls_connection(struct worker_st *ws) { int ret; gnutls_session_t session; gnutls_datum_t master = { ws->master_secret, sizeof(ws->master_secret) }; gnutls_datum_t sid = { ws->session_id, sizeof(ws->session_id) }; if (ws->req.selected_ciphersuite == NULL) { oclog(ws, LOG_ERR, "no DTLS ciphersuite negotiated"); return -1; } oclog(ws, LOG_DEBUG, "setting up DTLS connection"); /* DTLS cookie verified. * Initialize session. */ ret = gnutls_init(&session, GNUTLS_SERVER|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK); if (ret < 0) { oclog(ws, LOG_ERR, "could not initialize TLS session: %s", gnutls_strerror(ret)); return -1; } ret = gnutls_priority_set_direct(session, ws->req. selected_ciphersuite->gnutls_name, NULL); if (ret < 0) { oclog(ws, LOG_ERR, "could not set TLS priority: %s", gnutls_strerror(ret)); goto fail; } ret = gnutls_session_set_premaster(session, GNUTLS_SERVER, ws->req. selected_ciphersuite->gnutls_version, GNUTLS_KX_RSA, ws->req. selected_ciphersuite->gnutls_cipher, ws->req. selected_ciphersuite->gnutls_mac, GNUTLS_COMP_NULL, &master, &sid); if (ret < 0) { oclog(ws, LOG_ERR, "could not set TLS premaster: %s", gnutls_strerror(ret)); goto fail; } ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, ws->creds->xcred); if (ret < 0) { oclog(ws, LOG_ERR, "could not set TLS credentials: %s", gnutls_strerror(ret)); goto fail; } gnutls_transport_set_push_function(session, dtls_push); gnutls_transport_set_pull_function(session, dtls_pull); gnutls_transport_set_pull_timeout_function(session, dtls_pull_timeout); gnutls_transport_set_ptr(session, &ws->dtls_tptr); gnutls_session_set_ptr(session, ws); gnutls_certificate_server_set_request(session, GNUTLS_CERT_IGNORE); gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); ws->udp_state = UP_HANDSHAKE; ws->dtls_session = session; return 0; fail: gnutls_deinit(session); return -1; }
void dtls_try_with_key_mtu(const char *name, const char *client_prio, gnutls_kx_algorithm_t client_kx, gnutls_sign_algorithm_t server_sign_algo, gnutls_sign_algorithm_t client_sign_algo, const gnutls_datum_t *serv_cert, const gnutls_datum_t *serv_key, const gnutls_datum_t *client_cert, const gnutls_datum_t *client_key, unsigned cert_flags, unsigned smtu) { int ret; char buffer[256]; /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_anon_server_credentials_t s_anoncred; gnutls_dh_params_t dh_params; const gnutls_datum_t p3 = { (unsigned char *) pkcs3, strlen(pkcs3) }; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_anon_client_credentials_t c_anoncred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN, version; /* General init. */ gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(6); reset_buffers(); /* Init server */ gnutls_anon_allocate_server_credentials(&s_anoncred); gnutls_certificate_allocate_credentials(&serverx509cred); ret = gnutls_certificate_set_x509_key_mem(serverx509cred, serv_cert, serv_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { fail("Could not set key/cert: %s\n", gnutls_strerror(ret)); } gnutls_dh_params_init(&dh_params); gnutls_dh_params_import_pkcs3(dh_params, &p3, GNUTLS_X509_FMT_PEM); gnutls_certificate_set_dh_params(serverx509cred, dh_params); gnutls_anon_set_server_dh_params(s_anoncred, dh_params); assert(gnutls_init(&server, GNUTLS_SERVER|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK)>=0); assert(gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred)>=0); assert(gnutls_credentials_set(server, GNUTLS_CRD_ANON, s_anoncred)>=0); assert(gnutls_priority_set_direct(server, "NORMAL:+ANON-ECDH:+ANON-DH:+ECDHE-RSA:+DHE-RSA:+RSA:+ECDHE-ECDSA:+CURVE-X25519", NULL)>=0); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_pull_timeout_function(server, server_pull_timeout_func); gnutls_transport_set_ptr(server, server); if (smtu) gnutls_dtls_set_mtu (server, smtu); /* Init client */ ret = gnutls_certificate_allocate_credentials(&clientx509cred); if (ret < 0) exit(1); if (cert_flags == USE_CERT) { ret = gnutls_certificate_set_x509_key_mem(clientx509cred, client_cert, client_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { fail("Could not set key/cert: %s\n", gnutls_strerror(ret)); } gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUIRE); } else if (cert_flags == ASK_CERT) { gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST); } #if 0 ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) exit(1); #endif ret = gnutls_init(&client, GNUTLS_CLIENT|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK); if (ret < 0) exit(1); assert(gnutls_anon_allocate_client_credentials(&c_anoncred)>=0); assert(gnutls_credentials_set(client, GNUTLS_CRD_ANON, c_anoncred)>=0); ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); if (ret < 0) exit(1); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_pull_timeout_function(client, client_pull_timeout_func); gnutls_transport_set_ptr(client, client); if (smtu) gnutls_dtls_set_mtu (client, smtu); ret = gnutls_priority_set_direct(client, client_prio, NULL); if (ret < 0) { exit(1); } success("negotiating %s\n", name); HANDSHAKE_DTLS(client, server); if (gnutls_kx_get(client) != client_kx) { fail("%s: got unexpected key exchange algorithm: %s (expected %s)\n", name, gnutls_kx_get_name(gnutls_kx_get(client)), gnutls_kx_get_name(client_kx)); exit(1); } /* test signature algorithm match */ version = gnutls_protocol_get_version(client); if (version >= GNUTLS_DTLS1_2) { ret = gnutls_sign_algorithm_get(server); if (ret != (int)server_sign_algo) { fail("%s: got unexpected server signature algorithm: %d/%s\n", name, ret, gnutls_sign_get_name(ret)); exit(1); } ret = gnutls_sign_algorithm_get_client(server); if (ret != (int)client_sign_algo) { fail("%s: got unexpected client signature algorithm: %d/%s\n", name, ret, gnutls_sign_get_name(ret)); exit(1); } ret = gnutls_sign_algorithm_get(client); if (ret != (int)server_sign_algo) { fail("%s: cl: got unexpected server signature algorithm: %d/%s\n", name, ret, gnutls_sign_get_name(ret)); exit(1); } ret = gnutls_sign_algorithm_get_client(client); if (ret != (int)client_sign_algo) { fail("%s: cl: got unexpected client signature algorithm: %d/%s\n", name, ret, gnutls_sign_get_name(ret)); exit(1); } } gnutls_record_send(server, MSG, strlen(MSG)); ret = gnutls_record_recv(client, buffer, sizeof(buffer)); if (ret == 0) { fail("client: Peer has closed the TLS connection\n"); exit(1); } else if (ret < 0) { fail("client: Error: %s\n", gnutls_strerror(ret)); exit(1); } if (ret != strlen(MSG) || memcmp(MSG, buffer, ret) != 0) { fail("client: Error in data received. Expected %d, got %d\n", (int)strlen(MSG), ret); exit(1); } gnutls_bye(client, GNUTLS_SHUT_RDWR); gnutls_bye(server, GNUTLS_SHUT_RDWR); gnutls_deinit(client); gnutls_deinit(server); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); gnutls_anon_free_server_credentials(s_anoncred); gnutls_anon_free_client_credentials(c_anoncred); gnutls_dh_params_deinit(dh_params); }
static void SetupNewSession(int index, NetworkAddress * networkAddress, bool client) { DTLS_Session * session = &sessions[index]; session->NetworkAddress = networkAddress; unsigned int flags; #if GNUTLS_VERSION_MAJOR >= 3 if (client) flags = GNUTLS_CLIENT | GNUTLS_DATAGRAM | GNUTLS_NONBLOCK; else flags = GNUTLS_SERVER | GNUTLS_DATAGRAM | GNUTLS_NONBLOCK; #else if (client) flags = GNUTLS_CLIENT; else flags = GNUTLS_SERVER; #endif if (gnutls_init(&session->Session, flags) == GNUTLS_E_SUCCESS) { gnutls_transport_set_pull_function(session->Session, DecryptCallBack); gnutls_transport_set_push_function(session->Session, SSLSendCallBack); #if GNUTLS_VERSION_MAJOR >= 3 gnutls_transport_set_pull_timeout_function(session->Session, ReceiveTimeout); #endif gnutls_transport_set_ptr(session->Session, session); if (certificate || !pskIdentity) { if (_CertCredentials) { gnutls_credentials_set(session->Session, GNUTLS_CRD_CERTIFICATE, _CertCredentials); } else if (gnutls_certificate_allocate_credentials(&_CertCredentials) == GNUTLS_E_SUCCESS) { if (certificate) { gnutls_datum_t certificateData; certificateData.data = certificate; certificateData.size = certificateLength; int format = GNUTLS_X509_FMT_PEM; if (certificateFormat == AwaCertificateFormat_ASN1) format = GNUTLS_X509_FMT_DER; // if (client) // gnutls_certificate_set_x509_trust_mem(session->Credentials, &certificateData, format); // else gnutls_certificate_set_x509_key_mem(_CertCredentials, &certificateData, &certificateData, format); } #if GNUTLS_VERSION_MAJOR >= 3 gnutls_certificate_set_verify_function(_CertCredentials, CertificateVerify); //gnutls_certificate_set_retrieve_function(xcred, cert_callback); //gnutls_session_set_verify_cert(session->Session, NULL, GNUTLS_VERIFY_DISABLE_CA_SIGN); #else gnutls_certificate_set_verify_flags(_CertCredentials, GNUTLS_VERIFY_DISABLE_CA_SIGN); #endif gnutls_credentials_set(session->Session, GNUTLS_CRD_CERTIFICATE, _CertCredentials); } } else if (pskIdentity) { if (client) { gnutls_psk_client_credentials_t credentials; if (gnutls_psk_allocate_client_credentials(&credentials) == GNUTLS_E_SUCCESS) { if (gnutls_psk_set_client_credentials(credentials, pskIdentity, &pskKey, GNUTLS_PSK_KEY_RAW) == GNUTLS_E_SUCCESS) { gnutls_credentials_set(session->Session, GNUTLS_CRD_PSK, credentials); session->Credentials = credentials; session->CredentialType = CredentialType_ClientPSK; } else { gnutls_psk_set_client_credentials_function(credentials, PSKClientCallBack); session->Credentials = credentials; session->CredentialType = CredentialType_ClientPSK; } } } else { gnutls_psk_server_credentials_t credentials; if (gnutls_psk_allocate_server_credentials(&credentials) == GNUTLS_E_SUCCESS) { gnutls_psk_set_server_credentials_function(credentials, PSKCallBack); gnutls_credentials_set(session->Session, GNUTLS_CRD_PSK, credentials); session->Credentials = credentials; session->CredentialType = CredentialType_ServerPSK; } } } gnutls_priority_set(session->Session, _PriorityCache); if (!client) { gnutls_certificate_server_set_request(session->Session, GNUTLS_CERT_REQUEST); // GNUTLS_CERT_IGNORE Don't require Client Cert } #if GNUTLS_VERSION_MAJOR >= 3 gnutls_handshake_set_timeout(session->Session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); #endif } }
static void dtls_mtu_try(const char *name, const char *client_prio, unsigned link_mtu, unsigned tunnel_mtu) { int ret; /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; unsigned dmtu; unsigned i; /* General init. */ gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(6); reset_buffers(); /* Init server */ assert(gnutls_certificate_allocate_credentials(&serverx509cred)>=0); assert(gnutls_certificate_set_x509_key_mem(serverx509cred, &server_cert, &server_key, GNUTLS_X509_FMT_PEM) >= 0); assert(gnutls_init(&server, GNUTLS_SERVER|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK) >= 0); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); assert(gnutls_priority_set_direct(server, "NORMAL:+ANON-ECDH:+ANON-DH:+ECDHE-RSA:+DHE-RSA:+RSA:+ECDHE-ECDSA:+CURVE-X25519", NULL) >= 0); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_pull_timeout_function(server, server_pull_timeout_func); gnutls_transport_set_ptr(server, server); /* Init client */ ret = gnutls_init(&client, GNUTLS_CLIENT|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK); if (ret < 0) exit(1); assert(gnutls_certificate_allocate_credentials(&clientx509cred) >= 0); assert(gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM)>=0); assert(gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred) >= 0); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_pull_timeout_function(client, client_pull_timeout_func); gnutls_transport_set_ptr(client, client); ret = gnutls_priority_set_direct(client, client_prio, NULL); if (ret < 0) { fail("%s: error in priority setting\n", name); exit(1); } success("negotiating %s\n", name); HANDSHAKE_DTLS(client, server); gnutls_dtls_set_mtu(client, link_mtu); dmtu = gnutls_dtls_get_data_mtu(client); if (dmtu != tunnel_mtu) { fail("%s: Calculated MTU (%d) does not match expected (%d)\n", name, dmtu, tunnel_mtu); } { char msg[dmtu+1]; memset(msg, 1, sizeof(msg)); ret = gnutls_record_send(client, msg, dmtu+1); if (ret != (int)GNUTLS_E_LARGE_PACKET) { myfail("could send larger packet than MTU (%d), ret: %d\n", dmtu, ret); } ret = gnutls_record_send(client, msg, dmtu); if (ret != (int)dmtu) { myfail("could not send %d bytes (sent %d)\n", dmtu, ret); } memset(msg, 2, dmtu); ret = gnutls_record_recv(server, msg, dmtu); if (ret != (int)dmtu) { myfail("could not receive %d bytes (received %d)\n", dmtu, ret); } for (i=0;i<dmtu;i++) assert(msg[i]==1); } gnutls_bye(client, GNUTLS_SHUT_RDWR); gnutls_bye(server, GNUTLS_SHUT_RDWR); gnutls_deinit(client); gnutls_deinit(server); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); }