void server_start (void) { /* this must be called once in the program */ gnutls_global_init (); gnutls_global_set_log_function (tls_log_func); // gnutls_global_set_log_level (99); generate_dh_params (); gnutls_psk_allocate_server_credentials (&server_pskcred); gnutls_psk_set_server_credentials_function (server_pskcred, pskfunc); gnutls_psk_set_server_dh_params (server_pskcred, dh_params); success ("Launched, generating DH parameters...\n"); /* Socket operations */ listen_sd = socket (AF_INET, SOCK_STREAM, 0); if (err == -1) { perror ("socket"); fail ("server: socket failed\n"); return; } 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); /* Server Port number */ setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (int)); err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv)); if (err == -1) { perror ("bind"); fail ("server: bind failed\n"); return; } err = listen (listen_sd, 1024); if (err == -1) { perror ("listen"); fail ("server: listen failed\n"); return; } success ("server: ready. Listening to port '%d'.\n", PORT); }
static void server (void) { /* this must be called once in the program */ gnutls_global_init (); gnutls_global_set_log_function (tls_log_func); if (debug) gnutls_global_set_log_level (4711); generate_dh_params (); gnutls_psk_allocate_server_credentials (&server_pskcred); gnutls_psk_set_server_credentials_function (server_pskcred, pskfunc); gnutls_psk_set_server_dh_params (server_pskcred, dh_params); client_len = sizeof (sa_cli); session = initialize_tls_session (); sd = accept (listen_sd, (SA *) & sa_cli, &client_len); if (debug) success ("server: connection from %s, port %d\n", inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf, sizeof (topbuf)), ntohs (sa_cli.sin_port)); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); ret = gnutls_handshake (session); if (ret < 0) { close (sd); gnutls_deinit (session); fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret)); return; } if (debug) success ("server: Handshake was completed\n"); /* see the Getting peer's information example */ /* print_info(session); */ i = 0; for (;;) { memset (buffer, 0, MAX_BUF + 1); ret = gnutls_record_recv (session, buffer, MAX_BUF); if (ret == 0) { if (debug) success ("server: Peer has closed the GnuTLS connection\n"); break; } else if (ret < 0) { fail ("server: Received corrupted data(%d). Closing...\n", ret); break; } else if (ret > 0) { /* echo data back to the client */ gnutls_record_send (session, buffer, strlen (buffer)); } } /* do not wait for the peer to close the connection. */ gnutls_bye (session, GNUTLS_SHUT_WR); close (sd); gnutls_deinit (session); close (listen_sd); gnutls_psk_free_server_credentials (server_pskcred); gnutls_dh_params_deinit (dh_params); gnutls_global_deinit (); if (debug) success ("server: finished\n"); }
int main (void) { int err, listen_sd, i; int sd, ret; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; int client_len; char topbuf[512]; gnutls_session_t session; char buffer[MAX_BUF + 1]; int optval = 1; /* to disallow usage of the blocking /dev/random */ gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); /* 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); gnutls_certificate_set_x509_key_file (x509_cred, CERTFILE, KEYFILE, GNUTLS_X509_FMT_PEM); gnutls_psk_allocate_server_credentials (&psk_cred); gnutls_psk_set_server_credentials_function (psk_cred, pskfunc); generate_dh_params (); gnutls_priority_init (&priority_cache, "NORMAL:PSK", NULL); gnutls_certificate_set_dh_params (x509_cred, dh_params); /* Socket operations */ listen_sd = socket (AF_INET, SOCK_STREAM, 0); SOCKET_ERR (listen_sd, "socket"); 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); /* Server Port number */ setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (int)); err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv)); SOCKET_ERR (err, "bind"); err = listen (listen_sd, 1024); SOCKET_ERR (err, "listen"); printf ("Server ready. Listening to port '%d'.\n\n", PORT); client_len = sizeof (sa_cli); for (;;) { session = initialize_tls_session (); sd = accept (listen_sd, (SA *) & sa_cli, &client_len); printf ("- connection from %s, port %d\n", inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf, sizeof (topbuf)), ntohs (sa_cli.sin_port)); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); ret = gnutls_handshake (session); if (ret < 0) { close (sd); gnutls_deinit (session); fprintf (stderr, "*** Handshake has failed (%s)\n\n", gnutls_strerror (ret)); continue; } printf ("- Handshake was completed\n"); /* see the Getting peer's information example */ /* print_info(session); */ i = 0; for (;;) { memset (buffer, 0, MAX_BUF + 1); ret = gnutls_record_recv (session, buffer, MAX_BUF); if (ret == 0) { printf ("\n- Peer has closed the GNUTLS connection\n"); break; } else if (ret < 0) { fprintf (stderr, "\n*** Received corrupted " "data(%d). Closing the connection.\n\n", ret); break; } else if (ret > 0) { /* echo data back to the client */ gnutls_record_send (session, buffer, strlen (buffer)); } } printf ("\n"); /* do not wait for the peer to close the connection. */ gnutls_bye (session, GNUTLS_SHUT_WR); close (sd); gnutls_deinit (session); } close (listen_sd); gnutls_certificate_free_credentials (x509_cred); gnutls_psk_free_server_credentials (psk_cred); gnutls_priority_deinit (priority_cache); gnutls_global_deinit (); return 0; }
int lrmd_init_remote_tls_server() { int rc; int filter; int port = crm_default_remote_port(); struct addrinfo hints, *res = NULL, *iter; char port_str[6]; // at most "65535" gnutls_datum_t psk_key = { NULL, 0 }; static struct mainloop_fd_callbacks remote_listen_fd_callbacks = { .dispatch = lrmd_remote_listen, .destroy = lrmd_remote_connection_destroy, }; crm_notice("Starting TLS listener on port %d", port); crm_gnutls_global_init(); gnutls_global_set_log_function(debug_log); if (pcmk__init_tls_dh(&dh_params) != GNUTLS_E_SUCCESS) { return -1; } gnutls_psk_allocate_server_credentials(&psk_cred_s); gnutls_psk_set_server_credentials_function(psk_cred_s, lrmd_tls_server_key_cb); gnutls_psk_set_server_dh_params(psk_cred_s, dh_params); /* The key callback won't get called until the first client connection * attempt. Do it once here, so we can warn the user at start-up if we can't * read the key. We don't error out, though, because it's fine if the key is * going to be added later. */ rc = lrmd_tls_set_key(&psk_key); if (rc != 0) { crm_warn("A cluster connection will not be possible until the key is available"); } gnutls_free(psk_key.data); memset(&hints, 0, sizeof(struct addrinfo)); /* Bind to the wildcard address (INADDR_ANY or IN6ADDR_ANY_INIT). * @TODO allow user to specify a specific address */ hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC; /* Return IPv6 or IPv4 */ hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; snprintf(port_str, sizeof(port_str), "%d", port); rc = getaddrinfo(NULL, port_str, &hints, &res); if (rc) { crm_err("Unable to get IP address info for local node: %s", gai_strerror(rc)); return -1; } iter = res; filter = AF_INET6; /* Try IPv6 addresses first, then IPv4 */ while (iter) { if (iter->ai_family == filter) { ssock = bind_and_listen(iter); } if (ssock != -1) { break; } iter = iter->ai_next; if (iter == NULL && filter == AF_INET6) { iter = res; filter = AF_INET; } } if (ssock < 0) { goto init_remote_cleanup; } mainloop_add_fd("pacemaker-remote-server", G_PRIORITY_DEFAULT, ssock, NULL, &remote_listen_fd_callbacks); rc = ssock; init_remote_cleanup: if (rc < 0) { close(ssock); ssock = 0; } else { crm_debug("Started TLS listener on port %d", port); } freeaddrinfo(res); return rc; }
int lrmd_init_remote_tls_server(int port) { int rc; int filter; struct addrinfo hints, *res = NULL, *iter; char port_str[16]; static struct mainloop_fd_callbacks remote_listen_fd_callbacks = { .dispatch = lrmd_remote_listen, .destroy = lrmd_remote_connection_destroy, }; crm_notice("Starting a tls listener on port %d.", port); crm_gnutls_global_init(); gnutls_global_set_log_function(debug_log); gnutls_dh_params_init(&dh_params); gnutls_dh_params_generate2(dh_params, 1024); gnutls_psk_allocate_server_credentials(&psk_cred_s); gnutls_psk_set_server_credentials_function(psk_cred_s, lrmd_tls_server_key_cb); gnutls_psk_set_server_dh_params(psk_cred_s, dh_params); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_PASSIVE; /* Only return socket addresses with wildcard INADDR_ANY or IN6ADDR_ANY_INIT */ hints.ai_family = AF_UNSPEC; /* Return IPv6 or IPv4 */ hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; snprintf(port_str, sizeof(port_str), "%d", port); rc = getaddrinfo(NULL, port_str, &hints, &res); if (rc) { crm_err("getaddrinfo: %s", gai_strerror(rc)); return -1; } iter = res; filter = AF_INET6; /* Try IPv6 addresses first, then IPv4 */ while (iter) { if (iter->ai_family == filter) { ssock = bind_and_listen(iter); } if (ssock != -1) { break; } iter = iter->ai_next; if (iter == NULL && filter == AF_INET6) { iter = res; filter = AF_INET; } } if (ssock < 0) { crm_err("unable to bind to address"); goto init_remote_cleanup; } mainloop_add_fd("lrmd-remote", G_PRIORITY_DEFAULT, ssock, NULL, &remote_listen_fd_callbacks); rc = ssock; init_remote_cleanup: if (rc < 0) { close(ssock); ssock = 0; } freeaddrinfo(res); return rc; }
static void server(int sd, const char *prio) { gnutls_psk_server_credentials_t server_pskcred; int ret; gnutls_session_t session; char buffer[MAX_BUF + 1]; /* this must be called once in the program */ global_init(); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(4711); side = "server"; gnutls_psk_allocate_server_credentials(&server_pskcred); gnutls_psk_set_server_credentials_hint(server_pskcred, "hint"); gnutls_psk_set_server_credentials_function(server_pskcred, pskfunc); gnutls_psk_set_server_dh_params(server_pskcred, dh_params); gnutls_init(&session, GNUTLS_SERVER); /* avoid calling all the priority functions, since the defaults * are adequate. */ gnutls_priority_set_direct(session, prio, NULL); gnutls_credentials_set(session, GNUTLS_CRD_PSK, server_pskcred); gnutls_transport_set_int(session, sd); ret = gnutls_handshake(session); if (ret < 0) { close(sd); gnutls_deinit(session); fail("server: Handshake has failed (%s)\n\n", gnutls_strerror(ret)); return; } if (debug) success("server: Handshake was completed\n"); /* see the Getting peer's information example */ /* print_info(session); */ for (;;) { memset(buffer, 0, MAX_BUF + 1); gnutls_record_set_timeout(session, 10000); ret = gnutls_record_recv(session, buffer, MAX_BUF); if (ret == 0) { if (debug) success ("server: Peer has closed the GnuTLS connection\n"); break; } else if (ret < 0) { fail("server: Received corrupted data(%d). Closing...\n", ret); break; } else if (ret > 0) { /* echo data back to the client */ gnutls_record_send(session, buffer, strlen(buffer)); } } /* do not wait for the peer to close the connection. */ gnutls_bye(session, GNUTLS_SHUT_WR); close(sd); gnutls_deinit(session); gnutls_psk_free_server_credentials(server_pskcred); gnutls_global_deinit(); if (debug) success("server: finished\n"); }
int dtls_gnutls_accept(struct conn *conn) { char sock_buf[SOCK_ADDR_BUFSIZE]; char cookie_buf[SOCK_ADDR_BUFSIZE]; struct dtls_gnutls_data *d; uint8_t buffer[2048]; int tlen, rc; time_t c_timer; int bits; gnutls_datum_t cookie_key; gnutls_dtls_prestate_st prestate; gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE); cw_dbg(DBG_DTLS, "Session cookie for %s generated: %s", sock_addr2str(&conn->addr, sock_buf), sock_hwaddrtostr((uint8_t *) (&cookie_key), sizeof(cookie_key), cookie_buf, "")); memset(&prestate, 0, sizeof(prestate)); tlen = dtls_gnutls_bio_read(conn, buffer, sizeof(buffer)); gnutls_dtls_cookie_send(&cookie_key, &conn->addr, sizeof(conn->addr), &prestate, (gnutls_transport_ptr_t) conn, dtls_gnutls_bio_write); rc = -1; c_timer = cw_timer_start(10); while (!cw_timer_timeout(c_timer)) { tlen = conn_q_recv_packet_peek(conn, buffer, sizeof(buffer)); if (tlen < 0 && errno == EAGAIN) continue; if (tlen < 0) { /* something went wrong, we should log a message */ continue; } rc = gnutls_dtls_cookie_verify(&cookie_key, &conn->addr, sizeof(conn->addr), buffer + 4, tlen - 4, &prestate); if (rc < 0) { cw_dbg(DBG_DTLS, "Cookie couldn't be verified: %s", gnutls_strerror(rc)); dtls_gnutls_bio_read(conn, buffer, sizeof(buffer)); continue; } break; } if (rc < 0) { cw_log(LOG_ERR, "Cookie couldn't be verified: %s", gnutls_strerror(rc)); return 0; } cw_dbg(DBG_DTLS, "Cookie verified! Starting handshake with %s ...", sock_addr2str(&conn->addr, sock_buf)); d = dtls_gnutls_data_create(conn, GNUTLS_SERVER | GNUTLS_DATAGRAM); if (!d) return 0; if (conn->dtls_psk_enable) { gnutls_psk_server_credentials_t cred; rc = gnutls_psk_allocate_server_credentials(&cred); if (rc != 0) { cw_log(LOG_ERR,"gnutls_psk_allocate_server_credentials() failed."); } /* GnuTLS will call psk_creds to ask for the key associated with the client's username.*/ gnutls_psk_set_server_credentials_function(cred, psk_creds); /* // Pass the "credentials" to the GnuTLS session. GnuTLS does NOT make an // internal copy of the information, so we have to keep the 'cred' structure // in memory (and not modify it) until we're done with this session.*/ rc = gnutls_credentials_set(d->session, GNUTLS_CRD_PSK, cred); if (rc != 0) { cw_log(LOG_ERR,"gnutls_credentials_set() failed.\n"); } } /* Generate Diffie-Hellman parameters - for use with DHE * kx algorithms. When short bit length is used, it might * be wise to regenerate parameters often. */ /*bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY); */ bits = conn->dtls_dhbits; gnutls_dh_params_init(&d->dh_params); cw_dbg(DBG_DTLS, "Generating DH params, %d", bits); gnutls_dh_params_generate2(d->dh_params, bits); cw_dbg(DBG_DTLS, "DH params generated, %d", bits); gnutls_certificate_set_dh_params(d->x509_cred, d->dh_params); gnutls_certificate_server_set_request(d->session, GNUTLS_CERT_REQUEST); gnutls_dtls_prestate_set(d->session, &prestate); c_timer = cw_timer_start(10); do { rc = gnutls_handshake(d->session); } while (!cw_timer_timeout(c_timer) && rc == GNUTLS_E_AGAIN); if (rc < 0) { cw_log(LOG_ERR, "Error in handshake with %s: %s", sock_addr2str(&conn->addr, sock_buf), gnutls_strerror(rc)); return 0; } cw_dbg(DBG_DTLS, "Handshake with %s successful.", sock_addr2str(&conn->addr, sock_buf)); conn->dtls_data = d; conn->read = dtls_gnutls_read; conn->write = dtls_gnutls_write; return 1; }
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 } }
int main (void) { /* * Variable init */ int err, listen_sd; int sd, ret; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; int client_len; char topbuf[512]; gnutls_session_t session; int optval = 1; /* * SSL TLS utility init * This will add the certificate files properly * to the TLS session we are about to create. */ gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); 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); gnutls_certificate_set_x509_key_file (x509_cred, CERTFILE, KEYFILE, GNUTLS_X509_FMT_PEM); gnutls_psk_allocate_server_credentials (&psk_cred); gnutls_psk_set_server_credentials_function (psk_cred, pskfunc); generate_dh_params (); gnutls_priority_init (&priority_cache, "NORMAL:PSK", NULL); gnutls_certificate_set_dh_params (x509_cred, dh_params); /* * Web server socket stuff */ listen_sd = socket (AF_INET, SOCK_STREAM, 0); SOCKET_ERR (listen_sd, "socket"); 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); /* Server Port number */ setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, sizeof (int)); err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv)); SOCKET_ERR (err, "bind"); err = listen (listen_sd, 1024); SOCKET_ERR (err, "listen"); /* * Listening for clients this will SSLize * the incoming connection by properly doing the "handshake" */ client_len = sizeof (sa_cli); for (;;) { session = initialize_tls_session (); sd = accept(listen_sd, (SA *) & sa_cli, &client_len); pid_t pid = fork(); if (pid == 0) break; else continue; } printf ("Connection received from %s:%d\n", inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf, sizeof (topbuf)), ntohs (sa_cli.sin_port)); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); ret = gnutls_handshake (session); if (ret < 0) { close (sd); gnutls_deinit (session); fprintf (stderr, "\tSSL handshake failed!\n\tError: %s\n\n", gnutls_strerror(ret)); } printf ("\tSSL handshake successful!\n"); /* * Send it for processing */ process_request(session); printf ("\n"); /* * Closing connection. */ gnutls_bye (session, GNUTLS_SHUT_WR); // close (sd); gnutls_deinit (session); /* * Properly closing the TLS connection * we created to the web server. */ close (listen_sd); gnutls_certificate_free_credentials (x509_cred); gnutls_psk_free_server_credentials (psk_cred); gnutls_priority_deinit (priority_cache); gnutls_global_deinit (); return 0; }
psk_server_credentials::psk_server_credentials ():credentials (GNUTLS_CRD_PSK) { RETWRAP (gnutls_psk_allocate_server_credentials (&cred)); set_ptr (cred); }
int main(void) { int err, listen_sd; int sd, ret; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; socklen_t client_len; char topbuf[512]; gnutls_session_t session; gnutls_certificate_credentials_t x509_cred; gnutls_psk_server_credentials_t psk_cred; gnutls_priority_t priority_cache; char buffer[MAX_BUF + 1]; int optval = 1; int kx; if (gnutls_check_version("3.1.4") == NULL) { fprintf(stderr, "GnuTLS 3.1.4 is required for this example\n"); exit(1); } 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); gnutls_certificate_set_x509_key_file(x509_cred, CERTFILE, KEYFILE, GNUTLS_X509_FMT_PEM); gnutls_psk_allocate_server_credentials(&psk_cred); gnutls_psk_set_server_credentials_function(psk_cred, pskfunc); generate_dh_params(); gnutls_priority_init(&priority_cache, "NORMAL:+PSK:+ECDHE-PSK:+DHE-PSK", NULL); gnutls_certificate_set_dh_params(x509_cred, dh_params); /* Socket operations */ listen_sd = socket(AF_INET, SOCK_STREAM, 0); SOCKET_ERR(listen_sd, "socket"); 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); /* Server Port number */ setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, sizeof(int)); err = bind(listen_sd, (struct sockaddr *) &sa_serv, sizeof(sa_serv)); SOCKET_ERR(err, "bind"); err = listen(listen_sd, 1024); SOCKET_ERR(err, "listen"); printf("Server ready. Listening to port '%d'.\n\n", PORT); client_len = sizeof(sa_cli); for (;;) { gnutls_init(&session, GNUTLS_SERVER); gnutls_priority_set(session, priority_cache); gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred); gnutls_credentials_set(session, GNUTLS_CRD_PSK, psk_cred); /* request client certificate if any. */ gnutls_certificate_server_set_request(session, GNUTLS_CERT_REQUEST); sd = accept(listen_sd, (struct sockaddr *) &sa_cli, &client_len); printf("- connection from %s, port %d\n", inet_ntop(AF_INET, &sa_cli.sin_addr, topbuf, sizeof(topbuf)), ntohs(sa_cli.sin_port)); gnutls_transport_set_int(session, sd); ret = gnutls_handshake(session); if (ret < 0) { close(sd); gnutls_deinit(session); fprintf(stderr, "*** Handshake has failed (%s)\n\n", gnutls_strerror(ret)); continue; } printf("- Handshake was completed\n"); kx = gnutls_kx_get(session); if (kx == GNUTLS_KX_PSK || kx == GNUTLS_KX_DHE_PSK || kx == GNUTLS_KX_ECDHE_PSK) { printf("- User %s was connected\n", gnutls_psk_server_get_username(session)); } /* see the Getting peer's information example */ /* print_info(session); */ for (;;) { ret = gnutls_record_recv(session, buffer, MAX_BUF); if (ret == 0) { printf ("\n- Peer has closed the GnuTLS connection\n"); break; } else if (ret < 0 && gnutls_error_is_fatal(ret) == 0) { fprintf(stderr, "*** Warning: %s\n", gnutls_strerror(ret)); } else if (ret < 0) { fprintf(stderr, "\n*** Received corrupted " "data(%d). Closing the connection.\n\n", ret); break; } else if (ret > 0) { /* echo data back to the client */ gnutls_record_send(session, buffer, ret); } } printf("\n"); /* do not wait for the peer to close the connection. */ gnutls_bye(session, GNUTLS_SHUT_WR); close(sd); gnutls_deinit(session); } close(listen_sd); gnutls_certificate_free_credentials(x509_cred); gnutls_psk_free_server_credentials(psk_cred); gnutls_priority_deinit(priority_cache); gnutls_global_deinit(); return 0; }