You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tls.cxx 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /* Copyright (C) 2011 TightVNC Team. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. #include <config.h>
  20. #endif
  21. #include <os/tls.h>
  22. #include <iomanip>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <sstream>
  27. #include <sys/types.h>
  28. #include <time.h>
  29. using namespace std;
  30. #if defined(HAVE_GNUTLS) && !defined(WIN32)
  31. #include <gnutls/gnutls.h>
  32. #include <gnutls/x509.h>
  33. #ifndef HAVE_GNUTLS_X509_CRT_PRINT
  34. /* Ancient GNUTLS... */
  35. #if !defined(GNUTLS_VERSION_NUMBER) && !defined(LIBGNUTLS_VERSION_NUMBER)
  36. #define GNUTLS_DIG_SHA1 GNUTLS_DIG_SHA
  37. #endif
  38. #define UNKNOWN_SUBJECT(err) \
  39. do { \
  40. ss << "unknown subject (" << gnutls_strerror(err) << "), "; \
  41. } while (0)
  42. #define UNKNOWN_ISSUER(err) \
  43. do { \
  44. ss << "unknown issuer (" << gnutls_strerror(err) << "), "; \
  45. } while (0)
  46. static void
  47. hexprint(ostringstream &ss, const char *data, size_t len)
  48. {
  49. size_t j;
  50. char tmp[3];
  51. if (len == 0)
  52. ss << "00";
  53. else {
  54. for (j = 0; j < len; j++) {
  55. snprintf(tmp, sizeof(tmp), "%.2x", (unsigned char) data[j]);
  56. ss << tmp;
  57. }
  58. }
  59. }
  60. /* Implementation based on gnutls_x509_crt_print from GNUTLS */
  61. int
  62. gnutls_x509_crt_print(gnutls_x509_crt_t cert,
  63. gnutls_certificate_print_formats_t format,
  64. gnutls_datum_t * out)
  65. {
  66. ostringstream ss;
  67. int err;
  68. char *dn;
  69. size_t dn_size = 0;
  70. /* Subject */
  71. err = gnutls_x509_crt_get_dn(cert, NULL, &dn_size);
  72. if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
  73. UNKNOWN_SUBJECT(err);
  74. else {
  75. dn = (char *)malloc(dn_size);
  76. if (dn == NULL) {
  77. UNKNOWN_SUBJECT(GNUTLS_E_MEMORY_ERROR);
  78. } else {
  79. err = gnutls_x509_crt_get_dn(cert, dn, &dn_size);
  80. if (err < 0) {
  81. UNKNOWN_SUBJECT(err);
  82. } else
  83. ss << "subject `" << dn << "', ";
  84. free(dn);
  85. }
  86. }
  87. /* Issuer */
  88. dn = NULL;
  89. dn_size = 0;
  90. err = gnutls_x509_crt_get_issuer_dn(cert, NULL, &dn_size);
  91. if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
  92. UNKNOWN_ISSUER(err);
  93. else {
  94. dn = (char *)malloc(dn_size);
  95. if (dn == NULL) {
  96. UNKNOWN_ISSUER(GNUTLS_E_MEMORY_ERROR);
  97. } else {
  98. err = gnutls_x509_crt_get_issuer_dn(cert, dn, &dn_size);
  99. if (err < 0)
  100. UNKNOWN_ISSUER(err);
  101. else
  102. ss << "issuer `" << dn << "', ";
  103. free(dn);
  104. }
  105. }
  106. /* Key algorithm and size */
  107. unsigned int bits;
  108. const char *name;
  109. name = gnutls_pk_algorithm_get_name( (gnutls_pk_algorithm_t)
  110. gnutls_x509_crt_get_pk_algorithm(cert, &bits));
  111. if (name == NULL)
  112. name = "Unknown";
  113. ss << name << " key " << bits << " bits, ";
  114. /* Signature algorithm */
  115. err = gnutls_x509_crt_get_signature_algorithm(cert);
  116. if (err < 0) {
  117. ss << "unknown signature algorithm (" << gnutls_strerror(err)
  118. << "), ";
  119. } else {
  120. const char *name;
  121. name = gnutls_sign_algorithm_get_name((gnutls_sign_algorithm_t)err);
  122. if (name == NULL)
  123. name = "Unknown";
  124. ss << "signed using " << name;
  125. if (err == GNUTLS_SIGN_RSA_MD5 || err == GNUTLS_SIGN_RSA_MD2)
  126. ss << " (broken!)";
  127. ss << ", ";
  128. }
  129. /* Validity */
  130. time_t tim;
  131. char s[42];
  132. size_t max = sizeof(s);
  133. struct tm t;
  134. tim = gnutls_x509_crt_get_activation_time(cert);
  135. if (gmtime_r(&tim, &t) == NULL)
  136. ss << "unknown activation (" << (unsigned long) tim << ")";
  137. else if (strftime(s, max, "%Y-%m-%d %H:%M:%S UTC", &t) == 0)
  138. ss << "failed activation (" << (unsigned long) tim << ")";
  139. else
  140. ss << "activated `" << s << "'";
  141. ss << ", ";
  142. tim = gnutls_x509_crt_get_expiration_time(cert);
  143. if (gmtime_r(&tim, &t) == NULL)
  144. ss << "unknown expiry (" << (unsigned long) tim << ")";
  145. else if (strftime(s, max, "%Y-%m-%d %H:%M:%S UTC", &t) == 0)
  146. ss << "failed expiry (" << (unsigned long) tim << ")";
  147. else
  148. ss << "expires `" << s << "'";
  149. ss << ", ";
  150. /* Fingerprint */
  151. char buffer[20];
  152. size_t size = sizeof(buffer);
  153. err = gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, buffer, &size);
  154. if (err < 0)
  155. ss << "unknown fingerprint (" << gnutls_strerror(err) << ")";
  156. else {
  157. ss << "SHA-1 fingerprint `";
  158. hexprint(ss, buffer, size);
  159. ss << "'";
  160. }
  161. out->data = (unsigned char *) strdup(ss.str().c_str());
  162. if (out->data == NULL)
  163. return GNUTLS_E_MEMORY_ERROR;
  164. out->size = strlen((char *)out->data);
  165. return 0;
  166. }
  167. #endif /* HAVE_GNUTLS_X509_CRT_PRINT */
  168. #endif /* HAVE_GNUTLS */