updated makefiles
[gnutls.git] / doc / examples / ex-cert-select.c
blobe99baf4601c4ab42700f90f5d783231a04491203
1 /* This example code is placed in the public domain. */
3 #ifdef HAVE_CONFIG_H
4 #include <config.h>
5 #endif
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <arpa/inet.h>
13 #include <unistd.h>
14 #include <gnutls/gnutls.h>
15 #include <gnutls/x509.h>
16 #include <gnutls/abstract.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
21 /* A TLS client that loads the certificate and key.
24 #define MAX_BUF 1024
25 #define MSG "GET / HTTP/1.0\r\n\r\n"
27 #define CERT_FILE "cert.pem"
28 #define KEY_FILE "key.pem"
29 #define CAFILE "/etc/ssl/certs/ca-certificates.crt"
31 extern int tcp_connect (void);
32 extern void tcp_close (int sd);
34 static int
35 cert_callback (gnutls_session_t session,
36 const gnutls_datum_t * req_ca_rdn, int nreqs,
37 const gnutls_pk_algorithm_t * sign_algos,
38 int sign_algos_length, gnutls_pcert_st ** pcert,
39 unsigned int *pcert_length, gnutls_privkey_t * pkey);
41 gnutls_pcert_st crt;
42 gnutls_privkey_t key;
44 /* Helper functions to load a certificate and key
45 * files into memory.
47 static gnutls_datum_t
48 load_file (const char *file)
50 FILE *f;
51 gnutls_datum_t loaded_file = { NULL, 0 };
52 long filelen;
53 void *ptr;
55 if (!(f = fopen (file, "r"))
56 || fseek (f, 0, SEEK_END) != 0
57 || (filelen = ftell (f)) < 0
58 || fseek (f, 0, SEEK_SET) != 0
59 || !(ptr = malloc ((size_t) filelen))
60 || fread (ptr, 1, (size_t) filelen, f) < (size_t) filelen)
62 if (f)
63 fclose (f);
64 return loaded_file;
67 loaded_file.data = ptr;
68 loaded_file.size = (unsigned int) filelen;
69 return loaded_file;
72 static void
73 unload_file (gnutls_datum_t data)
75 free (data.data);
78 /* Load the certificate and the private key.
80 static void
81 load_keys (void)
83 int ret;
84 gnutls_datum_t data;
85 gnutls_x509_privkey_t x509_key;
87 data = load_file (CERT_FILE);
88 if (data.data == NULL)
90 fprintf (stderr, "*** Error loading certificate file.\n");
91 exit (1);
94 ret = gnutls_pcert_import_x509_raw (&crt, &data, GNUTLS_X509_FMT_PEM, 0);
95 if (ret < 0)
97 fprintf (stderr, "*** Error loading certificate file: %s\n",
98 gnutls_strerror (ret));
99 exit (1);
102 unload_file (data);
104 data = load_file (KEY_FILE);
105 if (data.data == NULL)
107 fprintf (stderr, "*** Error loading key file.\n");
108 exit (1);
111 gnutls_x509_privkey_init (&x509_key);
113 ret = gnutls_x509_privkey_import (x509_key, &data, GNUTLS_X509_FMT_PEM);
114 if (ret < 0)
116 fprintf (stderr, "*** Error loading key file: %s\n",
117 gnutls_strerror (ret));
118 exit (1);
121 gnutls_privkey_init (&key);
123 ret =
124 gnutls_privkey_import_x509 (key, x509_key,
125 GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
126 if (ret < 0)
128 fprintf (stderr, "*** Error importing key: %s\n",
129 gnutls_strerror (ret));
130 exit (1);
133 unload_file (data);
137 main (void)
139 int ret, sd, ii;
140 gnutls_session_t session;
141 gnutls_priority_t priorities_cache;
142 char buffer[MAX_BUF + 1];
143 gnutls_certificate_credentials_t xcred;
144 /* Allow connections to servers that have OpenPGP keys as well.
147 gnutls_global_init ();
149 load_keys ();
151 /* X509 stuff */
152 gnutls_certificate_allocate_credentials (&xcred);
154 /* priorities */
155 gnutls_priority_init (&priorities_cache, "NORMAL", NULL);
158 /* sets the trusted cas file
160 gnutls_certificate_set_x509_trust_file (xcred, CAFILE, GNUTLS_X509_FMT_PEM);
162 gnutls_certificate_set_retrieve_function2 (xcred, cert_callback);
164 /* Initialize TLS session
166 gnutls_init (&session, GNUTLS_CLIENT);
168 /* Use default priorities */
169 gnutls_priority_set (session, priorities_cache);
171 /* put the x509 credentials to the current session
173 gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred);
175 /* connect to the peer
177 sd = tcp_connect ();
179 gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
181 /* Perform the TLS handshake
183 ret = gnutls_handshake (session);
185 if (ret < 0)
187 fprintf (stderr, "*** Handshake failed\n");
188 gnutls_perror (ret);
189 goto end;
191 else
193 printf ("- Handshake was completed\n");
196 gnutls_record_send (session, MSG, strlen (MSG));
198 ret = gnutls_record_recv (session, buffer, MAX_BUF);
199 if (ret == 0)
201 printf ("- Peer has closed the TLS connection\n");
202 goto end;
204 else if (ret < 0)
206 fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret));
207 goto end;
210 printf ("- Received %d bytes: ", ret);
211 for (ii = 0; ii < ret; ii++)
213 fputc (buffer[ii], stdout);
215 fputs ("\n", stdout);
217 gnutls_bye (session, GNUTLS_SHUT_RDWR);
219 end:
221 tcp_close (sd);
223 gnutls_deinit (session);
225 gnutls_certificate_free_credentials (xcred);
226 gnutls_priority_deinit (priorities_cache);
228 gnutls_global_deinit ();
230 return 0;
235 /* This callback should be associated with a session by calling
236 * gnutls_certificate_client_set_retrieve_function( session, cert_callback),
237 * before a handshake.
240 static int
241 cert_callback (gnutls_session_t session,
242 const gnutls_datum_t * req_ca_rdn, int nreqs,
243 const gnutls_pk_algorithm_t * sign_algos,
244 int sign_algos_length, gnutls_pcert_st ** pcert,
245 unsigned int *pcert_length, gnutls_privkey_t * pkey)
247 char issuer_dn[256];
248 int i, ret;
249 size_t len;
250 gnutls_certificate_type_t type;
252 /* Print the server's trusted CAs
254 if (nreqs > 0)
255 printf ("- Server's trusted authorities:\n");
256 else
257 printf ("- Server did not send us any trusted authorities names.\n");
259 /* print the names (if any) */
260 for (i = 0; i < nreqs; i++)
262 len = sizeof (issuer_dn);
263 ret = gnutls_x509_rdn_get (&req_ca_rdn[i], issuer_dn, &len);
264 if (ret >= 0)
266 printf (" [%d]: ", i);
267 printf ("%s\n", issuer_dn);
271 /* Select a certificate and return it.
272 * The certificate must be of any of the "sign algorithms"
273 * supported by the server.
275 type = gnutls_certificate_type_get (session);
276 if (type == GNUTLS_CRT_X509)
278 *pcert_length = 1;
279 *pcert = &crt;
280 *pkey = key;
282 else
284 return -1;
287 return 0;