// demo0.cpp : Defines the entry point for the console application. // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SA struct sockaddr #define SOCKET_ERR(err,s) if(err==-1) {perror(s);return(1);} #define MAX_BUF 1024 #define PORT 5556 void DisplayError(); #define CERT_FILE "ttcert.pem" #define KEY_FILE "ttkey.pem" #define CAFILE "ca.pem" gnutls_certificate_credentials_t x509_cred; gnutls_x509_crt_t crt; gnutls_x509_privkey_t key; static gnutls_datum_t load_file (const char *file) { FILE *f; gnutls_datum_t loaded_file = { NULL, 0 }; long filelen; void *ptr; if (!(f = fopen (file, "r")) || fseek (f, 0, SEEK_END) != 0 || (filelen = ftell (f)) < 0 || fseek (f, 0, SEEK_SET) != 0 || !(ptr = malloc ((size_t) filelen)) || fread (ptr, 1, (size_t) filelen, f) < (size_t) filelen) { return loaded_file; } loaded_file.data = (unsigned char*)ptr; loaded_file.size = (unsigned int) filelen; return loaded_file; } static void unload_file (gnutls_datum_t data) { free (data.data); } static void load_keys() { int ret; gnutls_datum_t data; data = load_file (CERT_FILE); if (data.data == NULL) { fprintf (stderr, "*** Error loading cert file.\n"); return; } gnutls_x509_crt_init (&crt); ret = gnutls_x509_crt_import (crt, &data, GNUTLS_X509_FMT_PEM); if (ret < 0) { fprintf (stderr, "*** Error loading key file: %s\n", gnutls_strerror (ret)); return; } unload_file (data); data = load_file (KEY_FILE); if (data.data == NULL) { fprintf (stderr, "*** Error loading key file.\n"); return; } gnutls_x509_privkey_init (&key); /*ret = gnutls_x509_privkey_import (key, &data, GNUTLS_X509_FMT_PEM); if (ret < 0) { fprintf (stderr, "*** Error loading key file: %s\n", gnutls_strerror (ret)); }*/ ret =gnutls_x509_privkey_import_pkcs8(key,&data,GNUTLS_X509_FMT_PEM,"moto",0); if (ret < 0) { fprintf (stderr, "*** Error loading key file: %s\n", gnutls_strerror (ret)); } unload_file (data); } gnutls_datum_t cacheItem; int db_store_func(void *, gnutls_datum_t key, gnutls_datum_t data) { cacheItem.size = data.size; cacheItem.data = (unsigned char*)malloc ((size_t) data.size); memcpy(cacheItem.data,data.data,data.size); return 0; } gnutls_datum_t db_retr_func(void *, gnutls_datum_t key) { gnutls_datum_t result = { NULL, 0 }; result = cacheItem; return cacheItem; } int db_remove_func(void *, gnutls_datum_t key) { return 0; } ssize_t pullFunc(gnutls_transport_ptr_t sock, void* buffer ,size_t size) { int ret = read((int)sock, (char*)buffer, size); return ret; } ssize_t pushFunc(gnutls_transport_ptr_t sock,const void* buffer, size_t size) { int ret = write((int)sock, (char*)buffer, size); return ret; } gnutls_priority_t priority_cache; static gnutls_session_t initialize_tls_session (void) { gnutls_session_t session; gnutls_init (&session, GNUTLS_SERVER); gnutls_priority_set (session, priority_cache); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred); // gnutls_db_set_store_function(session,db_store_func); // gnutls_db_set_retrieve_function(session,db_retr_func); // gnutls_db_set_remove_function(session,db_remove_func); /* request client certificate if any. */ //gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST); /* Set maximum compatibility mode. This is only suggested on public webservers * that need to trade security for compatibility */ //gnutls_session_enable_compatibility_mode (session); gnutls_transport_set_pull_function(session,pullFunc); gnutls_transport_set_push_function(session,pushFunc); return session; } void print_info (gnutls_session_t session) { const char *tmp; gnutls_credentials_type_t cred; gnutls_kx_algorithm_t kx; /* print the key exchange¡¯s algorithm name */ kx = gnutls_kx_get (session); tmp = gnutls_kx_get_name (kx); printf ("- Key Exchange: %s\n", tmp); /* Check the authentication type used and switch * to the appropriate. */ cred = gnutls_auth_get_type (session); switch (cred) { case GNUTLS_CRD_IA: printf ("- TLS/IA session\n"); break; #ifdef ENABLE_SRP case GNUTLS_CRD_SRP: printf ("- SRP session with username %s\n", gnutls_srp_server_get_username (session)); break; #endif case GNUTLS_CRD_PSK: /* This returns NULL in server side. */ if (gnutls_psk_client_get_hint (session) != NULL) printf ("- PSK authentication. PSK hint ¡¯%s¡¯\n", gnutls_psk_client_get_hint (session)); /* This returns NULL in client side. */ if (gnutls_psk_server_get_username (session) != NULL) printf ("- PSK authentication. Connected as ¡¯%s¡¯\n", gnutls_psk_server_get_username (session)); break; case GNUTLS_CRD_ANON: /* anonymous authentication */ printf ("- Anonymous DH using prime of %d bits\n", gnutls_dh_get_prime_bits (session)); break; case GNUTLS_CRD_CERTIFICATE: /* certificate authentication */ /* Check if we have been using ephemeral Diffie-Hellman. */ if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS) { printf ("\n- Ephemeral DH using prime of %d bits\n", gnutls_dh_get_prime_bits (session)); } /* if the certificate list is available, then * print some information about it. */ //print_x509_certificate_info (session); } /* switch */ /* print the protocol¡¯s name (ie TLS 1.0) */ tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session)); printf ("- Protocol: %s\n", tmp); /* print the certificate type of the peer. * ie X.509 */ tmp = gnutls_certificate_type_get_name (gnutls_certificate_type_get (session)); printf ("- Certificate Type: %s\n", tmp); /* print the compression algorithm (if any) */ tmp = gnutls_compression_get_name (gnutls_compression_get (session)); printf ("- Compression: %s\n", tmp); /* print the name of the cipher used. * ie 3DES. */ tmp = gnutls_cipher_get_name (gnutls_cipher_get (session)); printf ("- Cipher: %s\n", tmp); /* Print the MAC algorithms name. * ie SHA1 */ tmp = gnutls_mac_get_name (gnutls_mac_get (session)); printf ("- MAC: %s\n", tmp); return; } int main(int argc, char* argv[]) { int err, listen_sd; int sd, ret; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; int client_len; char topbuf[512]; char buffer[MAX_BUF + 1]; int optval = 1; gnutls_session_t session; struct pollfd client; bool handshake; gnutls_global_init (); gnutls_certificate_allocate_credentials (&x509_cred); load_keys(); ret = gnutls_certificate_set_x509_key(x509_cred,&crt,1,key); gnutls_priority_init (&priority_cache, "NORMAL:+VERS-TLS1.2", NULL); if(ret <0) { fprintf (stderr, "*** Error loading key file: %s\n", gnutls_strerror (ret)); } /* 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, (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); while(1) { char* t = new char[100]; session = initialize_tls_session (); handshake = true; //gnutls_transport_set_pull_function(session,pullFunc); sd = accept (listen_sd, (SA *)& sa_cli, (socklen_t*)&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); //int flags = fcntl(sd, F_GETFL, 0); //fcntl(sd, F_SETFL, flags | O_NONBLOCK); client.fd = sd; client.events = POLLRDNORM; while(1) { ret = poll(&client,1,-1); if(ret > 0) { if(handshake) { ret = gnutls_handshake (session); if (ret < 0 && gnutls_error_is_fatal (ret)) { fprintf (stderr, "*** Handshake has failed (%s)\n\n",gnutls_strerror (ret)); break; } else if(ret <0) { printf("non-fatal error(%s), go on...\n",gnutls_strerror (ret)); } else { printf ("- Handshake was completed\n"); print_info(session); handshake = false; } } else { 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", ret); break; } else if (ret > 0) { printf("data received, %d %s\n",ret,buffer); gnutls_record_send (session, buffer, strlen (buffer)); } } } else { printf("Socket abnormal situation...\n"); } } printf("close session and socket\n"); gnutls_bye (session, GNUTLS_SHUT_RDWR); close(sd); gnutls_deinit (session); } close(listen_sd); gnutls_certificate_free_credentials(x509_cred); gnutls_priority_deinit(priority_cache); gnutls_global_deinit(); printf("end of test!\n"); while(1) { sleep(10); } return 0; }