Tizen 2.0 Release
[external/libgnutls26.git] / doc / examples / ex-rfc2818.c
1 /* This example code is placed in the public domain. */
2
3 #ifdef HAVE_CONFIG_H
4 #include <config.h>
5 #endif
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <gnutls/gnutls.h>
11 #include <gnutls/x509.h>
12 #include "examples.h"
13
14 /* A very basic TLS client, with X.509 authentication and server certificate
15  * verification.
16  */
17
18 #define MAX_BUF 1024
19 #define CAFILE "ca.pem"
20 #define MSG "GET / HTTP/1.0\r\n\r\n"
21
22 extern int tcp_connect (void);
23 extern void tcp_close (int sd);
24
25 /* This function will try to verify the peer's certificate, and
26  * also check if the hostname matches, and the activation, expiration dates.
27  */
28 static int
29 verify_certificate_callback (gnutls_session_t session)
30 {
31   unsigned int status;
32   const gnutls_datum_t *cert_list;
33   unsigned int cert_list_size;
34   int ret;
35   gnutls_x509_crt_t cert;
36   const char *hostname;
37
38   /* read hostname */
39   hostname = gnutls_session_get_ptr (session);
40
41   /* This verification function uses the trusted CAs in the credentials
42    * structure. So you must have installed one or more CA certificates.
43    */
44   ret = gnutls_certificate_verify_peers2 (session, &status);
45   if (ret < 0)
46     {
47       printf ("Error\n");
48       return GNUTLS_E_CERTIFICATE_ERROR;
49     }
50
51   if (status & GNUTLS_CERT_INVALID)
52     printf ("The certificate is not trusted.\n");
53
54   if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
55     printf ("The certificate hasn't got a known issuer.\n");
56
57   if (status & GNUTLS_CERT_REVOKED)
58     printf ("The certificate has been revoked.\n");
59
60   if (status & GNUTLS_CERT_EXPIRED)
61     printf ("The certificate has expired\n");
62
63   if (status & GNUTLS_CERT_NOT_ACTIVATED)
64     printf ("The certificate is not yet activated\n");
65
66   /* Up to here the process is the same for X.509 certificates and
67    * OpenPGP keys. From now on X.509 certificates are assumed. This can
68    * be easily extended to work with openpgp keys as well.
69    */
70   if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509)
71     return GNUTLS_E_CERTIFICATE_ERROR;
72
73   if (gnutls_x509_crt_init (&cert) < 0)
74     {
75       printf ("error in initialization\n");
76       return GNUTLS_E_CERTIFICATE_ERROR;
77     }
78
79   cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
80   if (cert_list == NULL)
81     {
82       printf ("No certificate was found!\n");
83       return GNUTLS_E_CERTIFICATE_ERROR;
84     }
85
86   /* This is not a real world example, since we only check the first 
87    * certificate in the given chain.
88    */
89   if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
90     {
91       printf ("error parsing certificate\n");
92       return GNUTLS_E_CERTIFICATE_ERROR;
93     }
94
95
96   if (!gnutls_x509_crt_check_hostname (cert, hostname))
97     {
98       printf ("The certificate's owner does not match hostname '%s'\n",
99               hostname);
100       return GNUTLS_E_CERTIFICATE_ERROR;
101     }
102
103   gnutls_x509_crt_deinit (cert);
104
105   /* notify gnutls to continue handshake normally */
106   return 0;
107 }
108
109
110 int
111 main (void)
112 {
113   int ret, sd, ii;
114   gnutls_session_t session;
115   char buffer[MAX_BUF + 1];
116   const char *err;
117   gnutls_certificate_credentials_t xcred;
118
119   gnutls_global_init ();
120
121   /* X509 stuff */
122   gnutls_certificate_allocate_credentials (&xcred);
123
124   /* sets the trusted cas file
125    */
126   gnutls_certificate_set_x509_trust_file (xcred, CAFILE, GNUTLS_X509_FMT_PEM);
127   gnutls_certificate_set_verify_function (xcred, verify_certificate_callback);
128   gnutls_certificate_set_verify_flags (xcred,
129                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
130
131   /* Initialize TLS session 
132    */
133   gnutls_init (&session, GNUTLS_CLIENT);
134
135   gnutls_session_set_ptr (session, (void *) "my_host_name");
136
137   /* Use default priorities */
138   ret = gnutls_priority_set_direct (session, "PERFORMANCE", &err);
139   if (ret < 0)
140     {
141       if (ret == GNUTLS_E_INVALID_REQUEST)
142         {
143           fprintf (stderr, "Syntax error at: %s\n", err);
144         }
145       exit (1);
146     }
147
148   /* put the x509 credentials to the current session
149    */
150   gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred);
151
152   /* connect to the peer
153    */
154   sd = tcp_connect ();
155
156   gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
157
158   /* Perform the TLS handshake
159    */
160   ret = gnutls_handshake (session);
161
162   if (ret < 0)
163     {
164       fprintf (stderr, "*** Handshake failed\n");
165       gnutls_perror (ret);
166       goto end;
167     }
168   else
169     {
170       printf ("- Handshake was completed\n");
171     }
172
173   gnutls_record_send (session, MSG, strlen (MSG));
174
175   ret = gnutls_record_recv (session, buffer, MAX_BUF);
176   if (ret == 0)
177     {
178       printf ("- Peer has closed the TLS connection\n");
179       goto end;
180     }
181   else if (ret < 0)
182     {
183       fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret));
184       goto end;
185     }
186
187   printf ("- Received %d bytes: ", ret);
188   for (ii = 0; ii < ret; ii++)
189     {
190       fputc (buffer[ii], stdout);
191     }
192   fputs ("\n", stdout);
193
194   gnutls_bye (session, GNUTLS_SHUT_RDWR);
195
196 end:
197
198   tcp_close (sd);
199
200   gnutls_deinit (session);
201
202   gnutls_certificate_free_credentials (xcred);
203
204   gnutls_global_deinit ();
205
206   return 0;
207 }