keylog.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * SPDX-License-Identifier: curl
  22. *
  23. ***************************************************************************/
  24. #include "../curl_setup.h"
  25. #if defined(USE_OPENSSL) || \
  26. defined(USE_GNUTLS) || \
  27. defined(USE_WOLFSSL) || \
  28. (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
  29. defined(USE_QUICHE) || \
  30. defined(USE_RUSTLS)
  31. #include "keylog.h"
  32. #include "../escape.h"
  33. #include "../curlx/fopen.h"
  34. /* The fp for the open SSLKEYLOGFILE, or NULL if not open */
  35. static FILE *keylog_file_fp;
  36. void Curl_tls_keylog_open(void)
  37. {
  38. char *keylog_file_name;
  39. if(!keylog_file_fp) {
  40. keylog_file_name = curl_getenv("SSLKEYLOGFILE");
  41. if(keylog_file_name) {
  42. keylog_file_fp = curlx_fopen(keylog_file_name, FOPEN_APPENDTEXT);
  43. if(keylog_file_fp) {
  44. #ifdef _WIN32
  45. if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
  46. #else
  47. if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
  48. #endif
  49. {
  50. curlx_fclose(keylog_file_fp);
  51. keylog_file_fp = NULL;
  52. }
  53. }
  54. Curl_safefree(keylog_file_name);
  55. }
  56. }
  57. }
  58. void Curl_tls_keylog_close(void)
  59. {
  60. if(keylog_file_fp) {
  61. curlx_fclose(keylog_file_fp);
  62. keylog_file_fp = NULL;
  63. }
  64. }
  65. bool Curl_tls_keylog_enabled(void)
  66. {
  67. return keylog_file_fp != NULL;
  68. }
  69. bool Curl_tls_keylog_write_line(const char *line)
  70. {
  71. /* The current maximum valid keylog line length LF and NUL is 195. */
  72. size_t linelen;
  73. char buf[256];
  74. if(!keylog_file_fp || !line) {
  75. return FALSE;
  76. }
  77. linelen = strlen(line);
  78. if(linelen == 0 || linelen > sizeof(buf) - 2) {
  79. /* Empty line or too big to fit in an LF and NUL. */
  80. return FALSE;
  81. }
  82. memcpy(buf, line, linelen);
  83. if(line[linelen - 1] != '\n') {
  84. buf[linelen++] = '\n';
  85. }
  86. buf[linelen] = '\0';
  87. /* Using fputs here instead of fprintf since libcurl's fprintf replacement
  88. may not be thread-safe. */
  89. fputs(buf, keylog_file_fp);
  90. return TRUE;
  91. }
  92. bool Curl_tls_keylog_write(const char *label,
  93. const unsigned char client_random[CLIENT_RANDOM_SIZE],
  94. const unsigned char *secret, size_t secretlen)
  95. {
  96. size_t pos, i;
  97. unsigned char line[KEYLOG_LABEL_MAXLEN + 1 + 2 * CLIENT_RANDOM_SIZE + 1 +
  98. 2 * SECRET_MAXLEN + 1 + 1];
  99. if(!keylog_file_fp) {
  100. return FALSE;
  101. }
  102. pos = strlen(label);
  103. if(pos > KEYLOG_LABEL_MAXLEN || !secretlen || secretlen > SECRET_MAXLEN) {
  104. /* Should never happen - sanity check anyway. */
  105. return FALSE;
  106. }
  107. memcpy(line, label, pos);
  108. line[pos++] = ' ';
  109. /* Client Random */
  110. for(i = 0; i < CLIENT_RANDOM_SIZE; i++) {
  111. Curl_hexbyte(&line[pos], client_random[i]);
  112. pos += 2;
  113. }
  114. line[pos++] = ' ';
  115. /* Secret */
  116. for(i = 0; i < secretlen; i++) {
  117. Curl_hexbyte(&line[pos], secret[i]);
  118. pos += 2;
  119. }
  120. line[pos++] = '\n';
  121. line[pos] = '\0';
  122. /* Using fputs here instead of fprintf since libcurl's fprintf replacement
  123. may not be thread-safe. */
  124. fputs((char *)line, keylog_file_fp);
  125. return TRUE;
  126. }
  127. #endif /* TLS or QUIC backend */