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