blob: 53b96674932805bcaf9eeb3eaf0702771406892a [file] [log] [blame]
Christian Heimesc7f70692019-05-31 11:44:05 +02001/* Debug helpers */
2
3static void
4_PySSL_msg_callback(int write_p, int version, int content_type,
5 const void *buf, size_t len, SSL *ssl, void *arg)
6{
7 const char *cbuf = (const char *)buf;
8 PyGILState_STATE threadstate;
9 PyObject *res = NULL;
10 PySSLSocket *ssl_obj = NULL; /* ssl._SSLSocket, borrowed ref */
11 PyObject *ssl_socket = NULL; /* ssl.SSLSocket or ssl.SSLObject */
12 int msg_type;
13
14 threadstate = PyGILState_Ensure();
15
16 ssl_obj = (PySSLSocket *)SSL_get_app_data(ssl);
17 assert(PySSLSocket_Check(ssl_obj));
18 if (ssl_obj->ctx->msg_cb == NULL) {
19 return;
20 }
21
22 if (ssl_obj->owner)
23 ssl_socket = PyWeakref_GetObject(ssl_obj->owner);
24 else if (ssl_obj->Socket)
25 ssl_socket = PyWeakref_GetObject(ssl_obj->Socket);
26 else
27 ssl_socket = (PyObject *)ssl_obj;
28 Py_INCREF(ssl_socket);
29
30 /* assume that OpenSSL verifies all payload and buf len is of sufficient
31 length */
32 switch(content_type) {
33 case SSL3_RT_CHANGE_CIPHER_SPEC:
34 msg_type = SSL3_MT_CHANGE_CIPHER_SPEC;
35 break;
36 case SSL3_RT_ALERT:
37 /* byte 0: level */
38 /* byte 1: alert type */
39 msg_type = (int)cbuf[1];
40 break;
41 case SSL3_RT_HANDSHAKE:
42 msg_type = (int)cbuf[0];
43 break;
44 case SSL3_RT_HEADER:
45 /* frame header encodes version in bytes 1..2 */
46 version = cbuf[1] << 8 | cbuf[2];
47 msg_type = (int)cbuf[0];
48 break;
49#ifdef SSL3_RT_INNER_CONTENT_TYPE
50 case SSL3_RT_INNER_CONTENT_TYPE:
51 msg_type = (int)cbuf[0];
52 break;
53#endif
54 default:
55 /* never SSL3_RT_APPLICATION_DATA */
56 msg_type = -1;
57 break;
58 }
59
60 res = PyObject_CallFunction(
61 ssl_obj->ctx->msg_cb, "Osiiiy#",
62 ssl_socket, write_p ? "write" : "read",
63 version, content_type, msg_type,
64 buf, len
65 );
66 if (res == NULL) {
67 PyErr_Fetch(&ssl_obj->exc_type, &ssl_obj->exc_value, &ssl_obj->exc_tb);
68 } else {
69 Py_DECREF(res);
70 }
71 Py_XDECREF(ssl_socket);
72
73 PyGILState_Release(threadstate);
74}
75
76
77static PyObject *
78_PySSLContext_get_msg_callback(PySSLContext *self, void *c) {
79 if (self->msg_cb != NULL) {
80 Py_INCREF(self->msg_cb);
81 return self->msg_cb;
82 } else {
83 Py_RETURN_NONE;
84 }
85}
86
87static int
88_PySSLContext_set_msg_callback(PySSLContext *self, PyObject *arg, void *c) {
89 Py_CLEAR(self->msg_cb);
90 if (arg == Py_None) {
91 SSL_CTX_set_msg_callback(self->ctx, NULL);
92 }
93 else {
94 if (!PyCallable_Check(arg)) {
95 SSL_CTX_set_msg_callback(self->ctx, NULL);
96 PyErr_SetString(PyExc_TypeError,
97 "not a callable object");
98 return -1;
99 }
100 Py_INCREF(arg);
101 self->msg_cb = arg;
102 SSL_CTX_set_msg_callback(self->ctx, _PySSL_msg_callback);
103 }
104 return 0;
105}
106
107#ifdef HAVE_OPENSSL_KEYLOG
108
109static void
110_PySSL_keylog_callback(const SSL *ssl, const char *line)
111{
112 PyGILState_STATE threadstate;
113 PySSLSocket *ssl_obj = NULL; /* ssl._SSLSocket, borrowed ref */
114 int res, e;
115 static PyThread_type_lock *lock = NULL;
116
117 threadstate = PyGILState_Ensure();
118
119 /* Allocate a static lock to synchronize writes to keylog file.
120 * The lock is neither released on exit nor on fork(). The lock is
121 * also shared between all SSLContexts although contexts may write to
122 * their own files. IMHO that's good enough for a non-performance
123 * critical debug helper.
124 */
125 if (lock == NULL) {
126 lock = PyThread_allocate_lock();
127 if (lock == NULL) {
128 PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
129 PyErr_Fetch(&ssl_obj->exc_type, &ssl_obj->exc_value,
130 &ssl_obj->exc_tb);
131 return;
132 }
133 }
134
135 ssl_obj = (PySSLSocket *)SSL_get_app_data(ssl);
136 assert(PySSLSocket_Check(ssl_obj));
137 if (ssl_obj->ctx->keylog_bio == NULL) {
138 return;
139 }
140
141 PySSL_BEGIN_ALLOW_THREADS
142 PyThread_acquire_lock(lock, 1);
143 res = BIO_printf(ssl_obj->ctx->keylog_bio, "%s\n", line);
144 e = errno;
145 (void)BIO_flush(ssl_obj->ctx->keylog_bio);
146 PyThread_release_lock(lock);
147 PySSL_END_ALLOW_THREADS
148
149 if (res == -1) {
150 errno = e;
151 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError,
152 ssl_obj->ctx->keylog_filename);
153 PyErr_Fetch(&ssl_obj->exc_type, &ssl_obj->exc_value, &ssl_obj->exc_tb);
154 }
155 PyGILState_Release(threadstate);
156}
157
158static PyObject *
159_PySSLContext_get_keylog_filename(PySSLContext *self, void *c) {
160 if (self->keylog_filename != NULL) {
161 Py_INCREF(self->keylog_filename);
162 return self->keylog_filename;
163 } else {
164 Py_RETURN_NONE;
165 }
166}
167
168static int
169_PySSLContext_set_keylog_filename(PySSLContext *self, PyObject *arg, void *c) {
170 FILE *fp;
171 /* Reset variables and callback first */
172 SSL_CTX_set_keylog_callback(self->ctx, NULL);
173 Py_CLEAR(self->keylog_filename);
174 if (self->keylog_bio != NULL) {
175 BIO *bio = self->keylog_bio;
176 self->keylog_bio = NULL;
177 PySSL_BEGIN_ALLOW_THREADS
178 BIO_free_all(bio);
179 PySSL_END_ALLOW_THREADS
180 }
181
182 if (arg == Py_None) {
183 /* None disables the callback */
184 return 0;
185 }
186
187 /* _Py_fopen_obj() also checks that arg is of proper type. */
188 fp = _Py_fopen_obj(arg, "a" PY_STDIOTEXTMODE);
189 if (fp == NULL)
190 return -1;
191
192 self->keylog_bio = BIO_new_fp(fp, BIO_CLOSE | BIO_FP_TEXT);
193 if (self->keylog_bio == NULL) {
194 PyErr_SetString(PySSLErrorObject,
195 "Can't malloc memory for keylog file");
196 return -1;
197 }
198 Py_INCREF(arg);
199 self->keylog_filename = arg;
200
201 /* Write a header for seekable, empty files (this excludes pipes). */
202 PySSL_BEGIN_ALLOW_THREADS
203 if (BIO_tell(self->keylog_bio) == 0) {
204 BIO_puts(self->keylog_bio,
205 "# TLS secrets log file, generated by OpenSSL / Python\n");
206 (void)BIO_flush(self->keylog_bio);
207 }
208 PySSL_END_ALLOW_THREADS
209 SSL_CTX_set_keylog_callback(self->ctx, _PySSL_keylog_callback);
210 return 0;
211}
212
213#endif