cb.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #include "tunala.h"
  2. #ifndef NO_OPENSSL
  3. /* For callbacks generating output, here are their file-descriptors. */
  4. static FILE *fp_cb_ssl_info = NULL;
  5. static FILE *fp_cb_ssl_verify = NULL;
  6. /*-
  7. * Output level:
  8. * 0 = nothing,
  9. * 1 = minimal, just errors,
  10. * 2 = minimal, all steps,
  11. * 3 = detail, all steps */
  12. static unsigned int cb_ssl_verify_level = 1;
  13. /* Other static rubbish (to mirror s_cb.c where required) */
  14. static int int_verify_depth = 10;
  15. /*
  16. * This function is largely borrowed from the one used in OpenSSL's
  17. * "s_client" and "s_server" utilities.
  18. */
  19. void cb_ssl_info(const SSL *s, int where, int ret)
  20. {
  21. const char *str1, *str2;
  22. int w;
  23. if (!fp_cb_ssl_info)
  24. return;
  25. w = where & ~SSL_ST_MASK;
  26. str1 = (w & SSL_ST_CONNECT ? "SSL_connect" : (w & SSL_ST_ACCEPT ?
  27. "SSL_accept" :
  28. "undefined")), str2 =
  29. SSL_state_string_long(s);
  30. if (where & SSL_CB_LOOP)
  31. fprintf(fp_cb_ssl_info, "(%s) %s\n", str1, str2);
  32. else if (where & SSL_CB_EXIT) {
  33. if (ret == 0)
  34. fprintf(fp_cb_ssl_info, "(%s) failed in %s\n", str1, str2);
  35. /*
  36. * In a non-blocking model, we get a few of these "error"s simply
  37. * because we're calling "reads" and "writes" on the state-machine
  38. * that are virtual NOPs simply to avoid wasting the time seeing if
  39. * we *should* call them. Removing this case makes the "-out_state"
  40. * output a lot easier on the eye.
  41. */
  42. # if 0
  43. else if (ret < 0)
  44. fprintf(fp_cb_ssl_info, "%s:error in %s\n", str1, str2);
  45. # endif
  46. }
  47. }
  48. void cb_ssl_info_set_output(FILE *fp)
  49. {
  50. fp_cb_ssl_info = fp;
  51. }
  52. static const char *int_reason_no_issuer =
  53. "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT";
  54. static const char *int_reason_not_yet = "X509_V_ERR_CERT_NOT_YET_VALID";
  55. static const char *int_reason_before =
  56. "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD";
  57. static const char *int_reason_expired = "X509_V_ERR_CERT_HAS_EXPIRED";
  58. static const char *int_reason_after =
  59. "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD";
  60. /* Stolen wholesale from apps/s_cb.c :-) And since then, mutilated ... */
  61. int cb_ssl_verify(int ok, X509_STORE_CTX *ctx)
  62. {
  63. char buf1[256]; /* Used for the subject name */
  64. char buf2[256]; /* Used for the issuer name */
  65. const char *reason = NULL; /* Error reason (if any) */
  66. X509 *err_cert;
  67. int err, depth;
  68. if (!fp_cb_ssl_verify || (cb_ssl_verify_level == 0))
  69. return ok;
  70. err_cert = X509_STORE_CTX_get_current_cert(ctx);
  71. err = X509_STORE_CTX_get_error(ctx);
  72. depth = X509_STORE_CTX_get_error_depth(ctx);
  73. buf1[0] = buf2[0] = '\0';
  74. /* Fill buf1 */
  75. X509_NAME_oneline(X509_get_subject_name(err_cert), buf1, 256);
  76. /* Fill buf2 */
  77. X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf2, 256);
  78. switch (ctx->error) {
  79. case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
  80. reason = int_reason_no_issuer;
  81. break;
  82. case X509_V_ERR_CERT_NOT_YET_VALID:
  83. reason = int_reason_not_yet;
  84. break;
  85. case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
  86. reason = int_reason_before;
  87. break;
  88. case X509_V_ERR_CERT_HAS_EXPIRED:
  89. reason = int_reason_expired;
  90. break;
  91. case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
  92. reason = int_reason_after;
  93. break;
  94. }
  95. if ((cb_ssl_verify_level == 1) && ok)
  96. return ok;
  97. fprintf(fp_cb_ssl_verify, "chain-depth=%d, ", depth);
  98. if (reason)
  99. fprintf(fp_cb_ssl_verify, "error=%s\n", reason);
  100. else
  101. fprintf(fp_cb_ssl_verify, "error=%d\n", err);
  102. if (cb_ssl_verify_level < 3)
  103. return ok;
  104. fprintf(fp_cb_ssl_verify, "--> subject = %s\n", buf1);
  105. fprintf(fp_cb_ssl_verify, "--> issuer = %s\n", buf2);
  106. if (!ok)
  107. fprintf(fp_cb_ssl_verify, "--> verify error:num=%d:%s\n", err,
  108. X509_verify_cert_error_string(err));
  109. fprintf(fp_cb_ssl_verify, "--> verify return:%d\n", ok);
  110. return ok;
  111. }
  112. void cb_ssl_verify_set_output(FILE *fp)
  113. {
  114. fp_cb_ssl_verify = fp;
  115. }
  116. void cb_ssl_verify_set_depth(unsigned int verify_depth)
  117. {
  118. int_verify_depth = verify_depth;
  119. }
  120. void cb_ssl_verify_set_level(unsigned int level)
  121. {
  122. if (level < 4)
  123. cb_ssl_verify_level = level;
  124. }
  125. RSA *cb_generate_tmp_rsa(SSL *s, int is_export, int keylength)
  126. {
  127. /*
  128. * TODO: Perhaps make it so our global key can be generated on-the-fly
  129. * after certain intervals?
  130. */
  131. static RSA *rsa_tmp = NULL;
  132. if (!rsa_tmp)
  133. rsa_tmp = RSA_generate_key(keylength, RSA_F4, NULL, NULL);
  134. return rsa_tmp;
  135. }
  136. #endif /* !defined(NO_OPENSSL) */