
#include <stdio.h>
#include <stdlib.h>
#include <gnutls/gnutls.h>

#define PRINTX(x,y) if (y[0]!=0) printf(" -   %s %s\n", x, y)
#define PRINT_DN(X) PRINTX( "CN:", X.common_name); \
        PRINTX( "OU:", X.organizational_unit_name); \
        PRINTX( "O:", X.organization); \
        PRINTX( "L:", X.locality_name); \
        PRINTX( "S:", X.state_or_province_name); \
        PRINTX( "C:", X.country); \
        PRINTX( "E:", X.email)

static void print_x509_certificate_info(gnutls_session);

/* This function will print some details of the
 * given session.
 */
int print_info(gnutls_session session)
{
   const char *tmp;
   gnutls_credentials_type cred;
   gnutls_kx_algorithm 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_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 0;
}

/* This function will print information about this session's peer
 * certificate. 
 */
static void print_x509_certificate_info(gnutls_session session)
{
   char digest[20];
   char serial[40];
   int digest_size = sizeof(digest), i;
   int serial_size = sizeof(serial);
   char printable[120];
   char *print;
   int algo, bits;
   time_t expiret = gnutls_certificate_expiration_time_peers(session);
   time_t activet = gnutls_certificate_activation_time_peers(session);
   const gnutls_datum *cert_list;
   int cert_list_size = 0;
   gnutls_x509_dn dn;

   cert_list = gnutls_certificate_get_peers(session, &cert_list_size);

   if (cert_list_size > 0
       && gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) {

      printf(" - Certificate info:\n");

      printf(" - Certificate is valid since: %s", ctime(&activet));
      printf(" - Certificate expires: %s", ctime(&expiret));

      /* Print the fingerprint of the certificate
       */
      if (gnutls_x509_fingerprint
          (GNUTLS_DIG_MD5, &cert_list[0], digest, &digest_size) >= 0) {
         print = printable;
         for (i = 0; i < digest_size; i++) {
            sprintf(print, "%.2x ", (unsigned char) digest[i]);
            print += 3;
         }
         printf(" - Certificate fingerprint: %s\n", printable);
      }

      /* Print the serial number of the certificate.
       */
      if (gnutls_x509_extract_certificate_serial
          (&cert_list[0], serial, &serial_size) >= 0) {
         print = printable;
         for (i = 0; i < serial_size; i++) {
            sprintf(print, "%.2x ", (unsigned char) serial[i]);
            print += 3;
         }
         printf(" - Certificate serial number: %s\n", printable);
      }

      /* Extract some of the public key algorithm's parameters
       */
      algo =
          gnutls_x509_extract_certificate_pk_algorithm(&cert_list[0],
                                                       &bits);
      printf("Certificate public key: ");

      if (algo == GNUTLS_PK_RSA) {
         printf("RSA\n");
         printf(" Modulus: %d bits\n", bits);
      } else if (algo == GNUTLS_PK_DSA) {
         printf("DSA\n");
         printf(" Exponent: %d bits\n", bits);
      } else {
         printf("UNKNOWN\n");
      }

      /* Print the version of the X.509 
       * certificate.
       */
      printf(" - Certificate version: #%d\n",
             gnutls_x509_extract_certificate_version(&cert_list[0]));

      gnutls_x509_extract_certificate_dn(&cert_list[0], &dn);
      PRINT_DN(dn);

      gnutls_x509_extract_certificate_issuer_dn(&cert_list[0], &dn);
      printf(" - Certificate Issuer's info:\n");
      PRINT_DN(dn);

   }
}

