Tizen 2.0 Release
[external/libgnutls26.git] / src / common.c
1 /*
2  * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
3  * 2009, 2010 Free Software Foundation, Inc.
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
8  * GnuTLS is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * GnuTLS is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <config.h>
23
24 /* Work around problem reported in
25    <http://permalink.gmane.org/gmane.comp.lib.gnulib.bugs/15755>.*/
26 #if GETTIMEOFDAY_CLOBBERS_LOCALTIME
27 #undef localtime
28 #endif
29
30 #include <getpass.h>
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <gnutls/gnutls.h>
36 #include <gnutls/x509.h>
37 #include <gnutls/openpgp.h>
38 #include <time.h>
39 #include <common.h>
40
41 #define SU(x) (x!=NULL?x:"Unknown")
42
43 int print_cert;
44 extern int verbose;
45
46 const char str_unknown[] = "(unknown)";
47
48 /* Hex encodes the given data.
49  */
50 const char *
51 raw_to_string (const unsigned char *raw, size_t raw_size)
52 {
53   static char buf[1024];
54   size_t i;
55   if (raw_size == 0)
56     return NULL;
57
58   if (raw_size * 3 + 1 >= sizeof (buf))
59     return NULL;
60
61   for (i = 0; i < raw_size; i++)
62     {
63       sprintf (&(buf[i * 3]), "%02X%s", raw[i],
64                (i == raw_size - 1) ? "" : ":");
65     }
66   buf[sizeof (buf) - 1] = '\0';
67
68   return buf;
69 }
70
71 static void
72 print_x509_info (gnutls_session_t session, const char *hostname, int insecure)
73 {
74   gnutls_x509_crt_t crt;
75   const gnutls_datum_t *cert_list;
76   unsigned int cert_list_size = 0, j;
77   int hostname_ok = 0;
78   int ret;
79
80   cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
81   if (cert_list_size == 0)
82     {
83       fprintf (stderr, "No certificates found!\n");
84       return;
85     }
86
87   printf (" - Got a certificate list of %d certificates.\n", cert_list_size);
88
89   for (j = 0; j < cert_list_size; j++)
90     {
91       gnutls_datum_t cinfo;
92
93       gnutls_x509_crt_init (&crt);
94       ret = gnutls_x509_crt_import (crt, &cert_list[j], GNUTLS_X509_FMT_DER);
95       if (ret < 0)
96         {
97           fprintf (stderr, "Decoding error: %s\n", gnutls_strerror (ret));
98           return;
99         }
100
101       printf (" - Certificate[%d] info:\n  - ", j);
102
103       if (verbose)
104         ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_FULL, &cinfo);
105       else
106         ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_ONELINE, &cinfo);
107       if (ret == 0)
108         {
109           printf ("%s\n", cinfo.data);
110           gnutls_free (cinfo.data);
111         }
112
113       if (print_cert)
114         {
115           size_t size = 0;
116           char *p = NULL;
117
118           ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_PEM, p, &size);
119           if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
120             {
121               p = malloc (size);
122               if (!p)
123                 {
124                   fprintf (stderr, "gnutls_malloc\n");
125                   exit (1);
126                 }
127
128               ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_PEM,
129                                             p, &size);
130             }
131           if (ret < 0)
132             {
133               fprintf (stderr, "Encoding error: %s\n", gnutls_strerror (ret));
134               return;
135             }
136
137           fputs ("\n", stdout);
138           fputs (p, stdout);
139           fputs ("\n", stdout);
140
141           gnutls_free (p);
142         }
143
144       if (j == 0 && hostname != NULL)
145         {
146           /* Check the hostname of the first certificate if it matches
147            * the name of the host we connected to.
148            */
149           if (gnutls_x509_crt_check_hostname (crt, hostname) == 0)
150             hostname_ok = 1;
151           else
152             hostname_ok = 2;
153         }
154
155       gnutls_x509_crt_deinit (crt);
156     }
157
158   if (hostname_ok == 1)
159     {
160       printf ("- The hostname in the certificate does NOT match '%s'\n",
161               hostname);
162       if (!insecure)
163         exit (1);
164     }
165   else if (hostname_ok == 2)
166     {
167       printf ("- The hostname in the certificate matches '%s'.\n", hostname);
168     }
169 }
170
171 #ifdef ENABLE_OPENPGP
172
173 static void
174 print_openpgp_info (gnutls_session_t session, const char *hostname,
175                     int insecure)
176 {
177
178   gnutls_openpgp_crt_t crt;
179   const gnutls_datum_t *cert_list;
180   int cert_list_size = 0;
181   int hostname_ok = 0;
182   int ret;
183
184   cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
185
186   if (cert_list_size > 0)
187     {
188       gnutls_datum_t cinfo;
189
190       gnutls_openpgp_crt_init (&crt);
191       ret = gnutls_openpgp_crt_import (crt, &cert_list[0],
192                                        GNUTLS_OPENPGP_FMT_RAW);
193       if (ret < 0)
194         {
195           fprintf (stderr, "Decoding error: %s\n", gnutls_strerror (ret));
196           return;
197         }
198
199       if (verbose)
200         ret = gnutls_openpgp_crt_print (crt, GNUTLS_CRT_PRINT_FULL, &cinfo);
201       else
202         ret =
203           gnutls_openpgp_crt_print (crt, GNUTLS_CRT_PRINT_ONELINE, &cinfo);
204       if (ret == 0)
205         {
206           printf (" - %s\n", cinfo.data);
207           gnutls_free (cinfo.data);
208         }
209
210       if (print_cert)
211         {
212           size_t size = 0;
213           char *p = NULL;
214
215           ret = gnutls_openpgp_crt_export (crt, GNUTLS_OPENPGP_FMT_BASE64,
216                                            p, &size);
217           if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
218             {
219               p = malloc (size);
220               if (!p)
221                 {
222                   fprintf (stderr, "gnutls_malloc\n");
223                   exit (1);
224                 }
225
226               ret = gnutls_openpgp_crt_export (crt, GNUTLS_OPENPGP_FMT_BASE64,
227                                                p, &size);
228             }
229           if (ret < 0)
230             {
231               fprintf (stderr, "Encoding error: %s\n", gnutls_strerror (ret));
232               return;
233             }
234
235           fputs (p, stdout);
236           fputs ("\n", stdout);
237
238           gnutls_free (p);
239         }
240
241       if (hostname != NULL)
242         {
243           /* Check the hostname of the first certificate if it matches
244            * the name of the host we connected to.
245            */
246           if (gnutls_openpgp_crt_check_hostname (crt, hostname) == 0)
247             hostname_ok = 1;
248           else
249             hostname_ok = 2;
250         }
251
252       gnutls_openpgp_crt_deinit (crt);
253     }
254
255   if (hostname_ok == 1)
256     {
257       printf ("- The hostname in the certificate does NOT match '%s'\n",
258               hostname);
259       if (!insecure)
260         exit (1);
261     }
262   else if (hostname_ok == 2)
263     {
264       printf ("- The hostname in the certificate matches '%s'.\n", hostname);
265     }
266 }
267
268 #endif
269
270 static void
271 print_cert_vrfy (gnutls_session_t session)
272 {
273   int rc;
274   unsigned int status;
275
276   rc = gnutls_certificate_verify_peers2 (session, &status);
277   if (rc < 0)
278     {
279       printf ("- Could not verify certificate (err: %s)\n",
280               gnutls_strerror (rc));
281       return;
282     }
283
284   if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND)
285     {
286       printf ("- Peer did not send any certificate.\n");
287       return;
288     }
289
290   if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509)
291     {
292       if (status & GNUTLS_CERT_REVOKED)
293         printf ("- Peer's certificate chain revoked\n");
294       if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
295         printf ("- Peer's certificate issuer is unknown\n");
296       if (status & GNUTLS_CERT_SIGNER_NOT_CA)
297         printf ("- Peer's certificate issuer is not a CA\n");
298       if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
299         printf ("- Peer's certificate chain uses insecure algorithm\n");
300       if (status & GNUTLS_CERT_NOT_ACTIVATED)
301         printf
302           ("- Peer's certificate chain uses not yet valid certificate\n");
303       if (status & GNUTLS_CERT_EXPIRED)
304         printf ("- Peer's certificate chain uses expired certificate\n");
305       if (status & GNUTLS_CERT_INVALID)
306         printf ("- Peer's certificate is NOT trusted\n");
307       else
308         printf ("- Peer's certificate is trusted\n");
309     }
310   else
311     {
312       if (status & GNUTLS_CERT_INVALID)
313         printf ("- Peer's key is invalid\n");
314       else
315         printf ("- Peer's key is valid\n");
316       if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
317         printf ("- Could not find a signer of the peer's key\n");
318     }
319 }
320
321 static void
322 print_dh_info (gnutls_session_t session, const char *str)
323 {
324   printf ("- %sDiffie-Hellman parameters\n", str);
325   printf (" - Using prime: %d bits\n", gnutls_dh_get_prime_bits (session));
326   printf (" - Secret key: %d bits\n", gnutls_dh_get_secret_bits (session));
327   printf (" - Peer's public key: %d bits\n",
328           gnutls_dh_get_peers_public_bits (session));
329
330   if (print_cert)
331     {
332       int ret;
333       gnutls_datum_t raw_gen = { NULL, 0 };
334       gnutls_datum_t raw_prime = { NULL, 0 };
335       gnutls_dh_params_t dh_params = NULL;
336       unsigned char *params_data = NULL;
337       size_t params_data_size = 0;
338
339       ret = gnutls_dh_get_group (session, &raw_gen, &raw_prime);
340       if (ret)
341         {
342           fprintf (stderr, "gnutls_dh_get_group %d\n", ret);
343           goto out;
344         }
345
346       ret = gnutls_dh_params_init (&dh_params);
347       if (ret)
348         {
349           fprintf (stderr, "gnutls_dh_params_init %d\n", ret);
350           goto out;
351         }
352
353       ret = gnutls_dh_params_import_raw (dh_params, &raw_prime, &raw_gen);
354       if (ret)
355         {
356           fprintf (stderr, "gnutls_dh_params_import_raw %d\n", ret);
357           goto out;
358         }
359
360       ret = gnutls_dh_params_export_pkcs3 (dh_params,
361                                            GNUTLS_X509_FMT_PEM,
362                                            params_data, &params_data_size);
363       if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
364         {
365           fprintf (stderr, "gnutls_dh_params_export_pkcs3 %d\n", ret);
366           goto out;
367         }
368
369       params_data = gnutls_malloc (params_data_size);
370       if (!params_data)
371         {
372           fprintf (stderr, "gnutls_malloc %d\n", ret);
373           goto out;
374         }
375
376       ret = gnutls_dh_params_export_pkcs3 (dh_params,
377                                            GNUTLS_X509_FMT_PEM,
378                                            params_data, &params_data_size);
379       if (ret)
380         {
381           fprintf (stderr, "gnutls_dh_params_export_pkcs3-2 %d\n", ret);
382           goto out;
383         }
384
385       printf (" - PKCS#3 format:\n\n%.*s\n", (int) params_data_size,
386               params_data);
387
388     out:
389       gnutls_free (params_data);
390       gnutls_free (raw_prime.data);
391       gnutls_free (raw_gen.data);
392       gnutls_dh_params_deinit (dh_params);
393     }
394 }
395
396 int
397 print_info (gnutls_session_t session, const char *hostname, int insecure)
398 {
399   const char *tmp;
400   gnutls_credentials_type_t cred;
401   gnutls_kx_algorithm_t kx;
402
403
404   /* print the key exchange's algorithm name
405    */
406   kx = gnutls_kx_get (session);
407
408   cred = gnutls_auth_get_type (session);
409   switch (cred)
410     {
411 #ifdef ENABLE_ANON
412     case GNUTLS_CRD_ANON:
413       print_dh_info (session, "Anonymous ");
414       break;
415 #endif
416 #ifdef ENABLE_SRP
417     case GNUTLS_CRD_SRP:
418       /* This should be only called in server
419        * side.
420        */
421       if (gnutls_srp_server_get_username (session) != NULL)
422         printf ("- SRP authentication. Connected as '%s'\n",
423                 gnutls_srp_server_get_username (session));
424       break;
425 #endif
426 #ifdef ENABLE_PSK
427     case GNUTLS_CRD_PSK:
428       /* This returns NULL in server side.
429        */
430       if (gnutls_psk_client_get_hint (session) != NULL)
431         printf ("- PSK authentication. PSK hint '%s'\n",
432                 gnutls_psk_client_get_hint (session));
433       /* This returns NULL in client side.
434        */
435       if (gnutls_psk_server_get_username (session) != NULL)
436         printf ("- PSK authentication. Connected as '%s'\n",
437                 gnutls_psk_server_get_username (session));
438       if (kx == GNUTLS_KX_DHE_PSK)
439         print_dh_info (session, "Ephemeral ");
440       break;
441 #endif
442     case GNUTLS_CRD_IA:
443       printf ("- TLS/IA authentication\n");
444       break;
445     case GNUTLS_CRD_CERTIFICATE:
446       {
447         char dns[256];
448         size_t dns_size = sizeof (dns);
449         unsigned int type;
450
451         /* This fails in client side */
452         if (gnutls_server_name_get (session, dns, &dns_size, &type, 0) == 0)
453           {
454             printf ("- Given server name[%d]: %s\n", type, dns);
455           }
456       }
457
458       if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS)
459         print_dh_info (session, "Ephemeral ");
460
461       print_cert_info (session, hostname, insecure);
462
463       print_cert_vrfy (session);
464
465     }
466
467   tmp = SU (gnutls_protocol_get_name (gnutls_protocol_get_version (session)));
468   printf ("- Version: %s\n", tmp);
469
470   tmp = SU (gnutls_kx_get_name (kx));
471   printf ("- Key Exchange: %s\n", tmp);
472
473   tmp = SU (gnutls_cipher_get_name (gnutls_cipher_get (session)));
474   printf ("- Cipher: %s\n", tmp);
475
476   tmp = SU (gnutls_mac_get_name (gnutls_mac_get (session)));
477   printf ("- MAC: %s\n", tmp);
478
479   tmp = SU (gnutls_compression_get_name (gnutls_compression_get (session)));
480   printf ("- Compression: %s\n", tmp);
481
482   if (verbose)
483     {
484       char id[32];
485       size_t id_size = sizeof (id);
486       gnutls_session_get_id (session, id, &id_size);
487       printf ("- Session ID: %s\n", raw_to_string (id, id_size));
488     }
489
490   if (verbose)
491     {
492       gnutls_datum cb;
493       int rc;
494
495       rc =
496         gnutls_session_channel_binding (session, GNUTLS_CB_TLS_UNIQUE, &cb);
497       if (rc)
498         fprintf (stderr, "Channel binding error: %s\n", gnutls_strerror (rc));
499       else
500         {
501           size_t i;
502
503           printf ("- Channel binding 'tls-unique': ");
504           for (i = 0; i < cb.size; i++)
505             printf ("%02x", cb.data[i]);
506           printf ("\n");
507         }
508     }
509
510   /* Warning: Do not print anything more here. The 'Compression:'
511      output MUST be the last non-verbose output.  This is used by
512      Emacs starttls.el code. */
513
514   fflush (stdout);
515
516   return 0;
517 }
518
519 void
520 print_cert_info (gnutls_session_t session, const char *hostname, int insecure)
521 {
522
523   if (gnutls_certificate_client_get_request_status (session) != 0)
524     printf ("- Server has requested a certificate.\n");
525
526   printf ("- Certificate type: ");
527   switch (gnutls_certificate_type_get (session))
528     {
529     case GNUTLS_CRT_UNKNOWN:
530       printf ("Unknown\n");
531
532       if (!insecure)
533         exit (1);
534       break;
535     case GNUTLS_CRT_X509:
536       printf ("X.509\n");
537       print_x509_info (session, hostname, insecure);
538       break;
539 #ifdef ENABLE_OPENPGP
540     case GNUTLS_CRT_OPENPGP:
541       printf ("OpenPGP\n");
542       print_openpgp_info (session, hostname, insecure);
543       break;
544 #endif
545     }
546 }
547
548 void
549 print_list (int verbose)
550 {
551   {
552     size_t i;
553     const char *name;
554     char id[2];
555     gnutls_kx_algorithm_t kx;
556     gnutls_cipher_algorithm_t cipher;
557     gnutls_mac_algorithm_t mac;
558     gnutls_protocol_t version;
559
560     printf ("Cipher suites:\n");
561     for (i = 0; (name = gnutls_cipher_suite_info
562                  (i, id, &kx, &cipher, &mac, &version)); i++)
563       {
564         printf ("%-50s\t0x%02x, 0x%02x\t%s\n",
565                 name,
566                 (unsigned char) id[0], (unsigned char) id[1],
567                 gnutls_protocol_get_name (version));
568         if (verbose)
569           printf ("\tKey exchange: %s\n\tCipher: %s\n\tMAC: %s\n\n",
570                   gnutls_kx_get_name (kx),
571                   gnutls_cipher_get_name (cipher), gnutls_mac_get_name (mac));
572       }
573   }
574
575   {
576     const gnutls_certificate_type_t *p = gnutls_certificate_type_list ();
577
578     printf ("Certificate types: ");
579     for (; *p; p++)
580       {
581         printf ("CTYPE-%s", gnutls_certificate_type_get_name (*p));
582         if (*(p + 1))
583           printf (", ");
584         else
585           printf ("\n");
586       }
587   }
588
589   {
590     const gnutls_protocol_t *p = gnutls_protocol_list ();
591
592     printf ("Protocols: ");
593     for (; *p; p++)
594       {
595         printf ("VERS-%s", gnutls_protocol_get_name (*p));
596         if (*(p + 1))
597           printf (", ");
598         else
599           printf ("\n");
600       }
601   }
602
603   {
604     const gnutls_cipher_algorithm_t *p = gnutls_cipher_list ();
605
606     printf ("Ciphers: ");
607     for (; *p; p++)
608       {
609         printf ("%s", gnutls_cipher_get_name (*p));
610         if (*(p + 1))
611           printf (", ");
612         else
613           printf ("\n");
614       }
615   }
616
617   {
618     const gnutls_mac_algorithm_t *p = gnutls_mac_list ();
619
620     printf ("MACs: ");
621     for (; *p; p++)
622       {
623         printf ("%s", gnutls_mac_get_name (*p));
624         if (*(p + 1))
625           printf (", ");
626         else
627           printf ("\n");
628       }
629   }
630
631   {
632     const gnutls_kx_algorithm_t *p = gnutls_kx_list ();
633
634     printf ("Key exchange algorithms: ");
635     for (; *p; p++)
636       {
637         printf ("%s", gnutls_kx_get_name (*p));
638         if (*(p + 1))
639           printf (", ");
640         else
641           printf ("\n");
642       }
643   }
644
645   {
646     const gnutls_compression_method_t *p = gnutls_compression_list ();
647
648     printf ("Compression: ");
649     for (; *p; p++)
650       {
651         printf ("COMP-%s", gnutls_compression_get_name (*p));
652         if (*(p + 1))
653           printf (", ");
654         else
655           printf ("\n");
656       }
657   }
658
659   {
660     const gnutls_pk_algorithm_t *p = gnutls_pk_list ();
661
662     printf ("Public Key Systems: ");
663     for (; *p; p++)
664       {
665         printf ("%s", gnutls_pk_algorithm_get_name (*p));
666         if (*(p + 1))
667           printf (", ");
668         else
669           printf ("\n");
670       }
671   }
672
673   {
674     const gnutls_sign_algorithm_t *p = gnutls_sign_list ();
675
676     printf ("PK-signatures: ");
677     for (; *p; p++)
678       {
679         printf ("SIGN-%s", gnutls_sign_algorithm_get_name (*p));
680         if (*(p + 1))
681           printf (", ");
682         else
683           printf ("\n");
684       }
685   }
686 }
687
688 void
689 sockets_init (void)
690 {
691 #ifdef _WIN32
692   WORD wVersionRequested;
693   WSADATA wsaData;
694
695   wVersionRequested = MAKEWORD (1, 1);
696   if (WSAStartup (wVersionRequested, &wsaData) != 0)
697     {
698       perror ("WSA_STARTUP_ERROR");
699     }
700 #endif
701 }
702
703 /* converts a service name or a port (in string) to a
704  * port number. The protocol is assumed to be TCP.
705  *
706  * returns -1 on error;
707  */
708 int
709 service_to_port (const char *service)
710 {
711   int port;
712   struct servent *server_port;
713
714   port = atoi (service);
715   if (port != 0)
716     return port;
717
718   server_port = getservbyname (service, "tcp");
719   if (server_port == NULL)
720     {
721       perror ("getservbyname()");
722       return (-1);
723     }
724
725   return ntohs (server_port->s_port);
726 }
727