1 /* This example code is placed in the public domain. */
10 #include <gnutls/gnutls.h>
11 #include <gnutls/x509.h>
14 /* A very basic TLS client, with X.509 authentication and server certificate
15 * verification. Note that error checking for missing files etc. is omitted
20 #define CAFILE "/etc/ssl/certs/ca-certificates.crt"
21 #define MSG "GET / HTTP/1.0\r\n\r\n"
23 extern int tcp_connect(void);
24 extern void tcp_close(int sd);
25 static int _verify_certificate_callback(gnutls_session_t session);
30 gnutls_session_t session;
31 char buffer[MAX_BUF + 1];
33 gnutls_certificate_credentials_t xcred;
35 if (gnutls_check_version("3.1.4") == NULL) {
36 fprintf(stderr, "GnuTLS 3.1.4 or later is required for this example\n");
40 /* for backwards compatibility with gnutls < 3.3.0 */
44 gnutls_certificate_allocate_credentials(&xcred);
46 /* sets the trusted cas file
48 gnutls_certificate_set_x509_trust_file(xcred, CAFILE,
50 gnutls_certificate_set_verify_function(xcred,
51 _verify_certificate_callback);
53 /* If client holds a certificate it can be set using the following:
55 gnutls_certificate_set_x509_key_file (xcred,
56 "cert.pem", "key.pem",
60 /* Initialize TLS session
62 gnutls_init(&session, GNUTLS_CLIENT);
64 gnutls_session_set_ptr(session, (void *) "my_host_name");
66 gnutls_server_name_set(session, GNUTLS_NAME_DNS, "my_host_name",
67 strlen("my_host_name"));
69 /* use default priorities */
70 gnutls_set_default_priority(session);
72 /* if more fine-graned control is required */
73 ret = gnutls_priority_set_direct(session,
76 if (ret == GNUTLS_E_INVALID_REQUEST) {
77 fprintf(stderr, "Syntax error at: %s\n", err);
83 /* put the x509 credentials to the current session
85 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
87 /* connect to the peer
91 gnutls_transport_set_int(session, sd);
92 gnutls_handshake_set_timeout(session,
93 GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
95 /* Perform the TLS handshake
98 ret = gnutls_handshake(session);
100 while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
103 fprintf(stderr, "*** Handshake failed\n");
109 desc = gnutls_session_get_desc(session);
110 printf("- Session info: %s\n", desc);
114 gnutls_record_send(session, MSG, strlen(MSG));
116 ret = gnutls_record_recv(session, buffer, MAX_BUF);
118 printf("- Peer has closed the TLS connection\n");
120 } else if (ret < 0 && gnutls_error_is_fatal(ret) == 0) {
121 fprintf(stderr, "*** Warning: %s\n", gnutls_strerror(ret));
122 } else if (ret < 0) {
123 fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret));
128 printf("- Received %d bytes: ", ret);
129 for (ii = 0; ii < ret; ii++) {
130 fputc(buffer[ii], stdout);
135 gnutls_bye(session, GNUTLS_SHUT_RDWR);
141 gnutls_deinit(session);
143 gnutls_certificate_free_credentials(xcred);
145 gnutls_global_deinit();
150 /* This function will verify the peer's certificate, and check
151 * if the hostname matches, as well as the activation, expiration dates.
153 static int _verify_certificate_callback(gnutls_session_t session)
157 const char *hostname;
161 hostname = gnutls_session_get_ptr(session);
163 /* This verification function uses the trusted CAs in the credentials
164 * structure. So you must have installed one or more CA certificates.
167 /* The following demonstrate two different verification functions,
168 * the more flexible gnutls_certificate_verify_peers(), as well
169 * as the old gnutls_certificate_verify_peers3(). */
172 gnutls_typed_vdata_st data[2];
174 memset(data, 0, sizeof(data));
176 data[0].type = GNUTLS_DT_DNS_HOSTNAME;
177 data[0].data = (void*)hostname;
179 data[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
180 data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER;
182 ret = gnutls_certificate_verify_peers(session, data, 2,
186 ret = gnutls_certificate_verify_peers3(session, hostname,
191 return GNUTLS_E_CERTIFICATE_ERROR;
194 type = gnutls_certificate_type_get(session);
197 gnutls_certificate_verification_status_print(status, type,
201 return GNUTLS_E_CERTIFICATE_ERROR;
204 printf("%s", out.data);
206 gnutls_free(out.data);
208 if (status != 0) /* Certificate is not trusted */
209 return GNUTLS_E_CERTIFICATE_ERROR;
211 /* notify gnutls to continue handshake normally */