CommunicationSecrets.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9#include "squid.h"
10#include "base/CharacterSet.h"
11#include "base/IoManip.h"
13#include "security/Session.h"
14
15#include <ostream>
16
17// TODO: Support SSL_CTX_set_keylog_callback() available since OpenSSL v1.1.1.
18
20{
21#if USE_OPENSSL
22 getClientRandom(sconn);
23
24 if (const auto session = SSL_get_session(&sconn)) {
25 getMasterKey(*session);
26 getSessionId(*session);
27 }
28#else
29 // Secret extraction is not supported in builds using other TLS libraries.
30 // Secret extraction is impractical in builds without TLS libraries.
31 (void)sconn;
32#endif
33}
34
35bool
37{
38 return !id.isEmpty() && !random.isEmpty() && !key.isEmpty();
39}
40
41bool
43{
44 auto sawChange = false;
45
46 if (id != news.id && !news.id.isEmpty()) {
47 id = news.id;
48 sawChange = true;
49 }
50
51 if (random != news.random && !news.random.isEmpty()) {
52 random = news.random;
53 sawChange = true;
54 }
55
56 if (key != news.key && !news.key.isEmpty()) {
57 key = news.key;
58 sawChange = true;
59 }
60
61 return sawChange;
62}
63
65static void
66PrintSecret(std::ostream &os, const SBuf &secret)
67{
68 if (!secret.isEmpty())
69 PrintHex(os, secret.rawContent(), secret.length());
70 else
71 os << '-';
72}
73
74void
76 // Print SSLKEYLOGFILE blobs that contain at least one known secret.
77 // See Wireshark tls_keylog_process_lines() source code for format details.
78
79 // RSA Session-ID:... Master-Key:...
80 if (id.length() || key.length()) {
81 os << "RSA";
82 PrintSecret(os << " Session-ID:", id);
83 PrintSecret(os << " Master-Key:", key);
84 os << "\n";
85 }
86
87 // CLIENT_RANDOM ... ...
88 if (random.length() || key.length()) {
89 os << "CLIENT_RANDOM ";
90 PrintSecret(os, random);
91 os << ' ';
92 // we may have already printed the key on a separate Master-Key: line above,
93 // but the CLIENT_RANDOM line format includes the same key info
94 PrintSecret(os, key);
95 os << "\n";
96 }
97}
98
99#if USE_OPENSSL
103static void
105{
106 static const auto NulChar = CharacterSet("NUL").add('\0');
107 if (secret.findFirstNotOf(NulChar) == SBuf::npos) // all zeros
108 secret.clear();
109}
110
111void
113{
114 random.clear();
115 const auto expectedLength = SSL_get_client_random(&sconn, nullptr, 0);
116 if (!expectedLength)
117 return;
118
119 // no auto due to reinterpret_casting of the result below
120 char * const space = random.rawAppendStart(expectedLength);
121 const auto actualLength = SSL_get_client_random(&sconn,
122 reinterpret_cast<unsigned char*>(space), expectedLength);
123 random.rawAppendFinish(space, actualLength);
124
125 IgnorePlaceholder(random);
126}
127
128void
130{
131 id.clear();
132 unsigned int idLength = 0;
133 // no auto due to reinterpret_casting of the result below
134 const unsigned char * const idStart = SSL_SESSION_get_id(&session, &idLength);
135 if (idStart && idLength)
136 id.assign(reinterpret_cast<const char *>(idStart), idLength);
137
139}
140
141void
143{
144 key.clear();
145 const auto expectedLength = SSL_SESSION_get_master_key(&session, nullptr, 0);
146 if (!expectedLength)
147 return;
148
149 // no auto due to reinterpret_casting of the result below
150 char * const space = key.rawAppendStart(expectedLength);
151 const auto actualLength = SSL_SESSION_get_master_key(&session,
152 reinterpret_cast<unsigned char*>(space), expectedLength);
153 key.rawAppendFinish(space, actualLength);
154
156}
157#endif /* USE_OPENSSL */
158
static void PrintSecret(std::ostream &os, const SBuf &secret)
writes the given secret (in hex) or, if there is no secret, a placeholder
static void IgnorePlaceholder(SBuf &secret)
void PrintHex(std::ostream &os, const char *const data, const size_t n)
Prints the first n data bytes using hex notation. Does nothing if n is 0.
Definition: IoManip.cc:16
optimized set of C chars, with quick membership test and merge support
Definition: CharacterSet.h:18
CharacterSet & add(const unsigned char c)
add a given character to the character set
Definition: CharacterSet.cc:47
Definition: SBuf.h:94
const char * rawContent() const
Definition: SBuf.cc:509
static const size_type npos
Definition: SBuf.h:99
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:415
size_type findFirstNotOf(const CharacterSet &set, size_type startPos=0) const
Definition: SBuf.cc:746
bool isEmpty() const
Definition: SBuf.h:431
void clear()
Definition: SBuf.cc:175
SBuf key
TLS session (pre-)master key.
SBuf random
CLIENT_RANDOM from the TLS connection.
void getClientRandom(const Connection &sconn)
void getMasterKey(const Session &session)
void getSessionId(const Session &session)
bool learnNew(const CommunicationSecrets &news)
void record(std::ostream &) const
logs all known secrets using a (multiline) SSLKEYLOGFILE format
bool gotAll() const
whether we know all the secrets that could be extracted
SSL_SESSION Session
Definition: Session.h:47
SSL Connection
Definition: Session.h:45
const unsigned char * SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
Definition: openssl.h:147
size_t SSL_get_client_random(const SSL *ssl, unsigned char *outStart, size_t outSizeMax)
Definition: openssl.h:157
size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *outStart, size_t outSizeMax)
Definition: openssl.h:178

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors