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