Index: doc/tls.html
==================================================================
--- doc/tls.html
+++ doc/tls.html
@@ -467,26 +467,40 @@
info channel major minor message type
This form of callback is invoked by the OpenSSL function
- SSL_CTX_set_info_callback()
.
+ SSL_CTX_set_info_callback()
during connection setup
+ and use.
- The major and minor arguments are used to
- represent the state information bitmask.
- Possible values for major are:
handshake, alert, connect, accept
.
- Possible values for minor are:
start, done, read, write, loop, exit
.
- The message argument is a descriptive string which may
be generated either by
SSL_state_string_long()
or by
SSL_alert_desc_string_long()
, depending on context.
- For alerts, the possible values for type are:
-
warning, fatal, and unknown
.
+ warning, fatal, and unknown
. For others,
+ info
is used.
+
+
+ message channel direction version content_type data
+
+
+ This form of callback is invoked by the OpenSSL function
+ SSL_set_msg_callback()
whenever a message is sent or
+ received. It is only available when
+ OpenSSL is complied with the enable-ssl-trace option.
+ Where direction is Sent or Received, version is the
+ protocol version, content_type is the message content type,
+ and data is more info on the message from the SSL_trace
API.
+
+
session session_id ticket lifetime
@@ -528,13 +542,13 @@
alpn protocol
For servers, this form of callback is invoked when the client ALPN
- extension is received and the first -alpn specified protocol common
- to the both the client and server is selected. If none, the first
- client specified protocol is used.
+ extension is received. Where protocol is the first
+ -alpn specified protocol common to the both the client and
+ server. If none, the first client specified protocol is used.
@@ -552,13 +566,14 @@
sni servername
For servers, this form of callback is invoked when the SNI extension
- from the client is received. This is used when a server supports multiple
- names, so the right certificate can be used. Called after hello
- callback but before ALPN callback.
+ from the client is received. Where servername is the client
+ provided server name from the -servername option. This is
+ used when a server supports multiple names, so the right certificate
+ can be used. Called after hello callback but before ALPN callback.
@@ -565,11 +580,12 @@
verify channel depth cert status error
This form of callback is invoked by OpenSSL when a new certificate
is received from the peer. It allows the client to check the
- certificate chain verification results and choose whether to continue or not.
+ certificate verification results and choose whether to continue
+ or not. It is called for each certificate in the certificate chain.
- The depth argument is an integer representing the
current depth on the certificate chain, with
0
as the peer certificate and higher values going
up to the Certificate Authority (CA).
Index: generic/tls.c
==================================================================
--- generic/tls.c
+++ generic/tls.c
@@ -149,11 +149,11 @@
/*
*-------------------------------------------------------------------
*
* InfoCallback --
*
- * monitors SSL connection process
+ * Monitors SSL connection process
*
* Results:
* None
*
* Side effects:
@@ -218,15 +218,132 @@
}
/*
*-------------------------------------------------------------------
*
+ * MessageCallback --
+ *
+ * Monitors SSL protocol messages
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Calls callback (if defined)
+ *
+ *-------------------------------------------------------------------
+ */
+#ifndef OPENSSL_NO_SSL_TRACE
+static void
+MessageCallback(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg) {
+ State *statePtr = (State*)arg;
+ Tcl_Interp *interp = statePtr->interp;
+ Tcl_Obj *cmdPtr;
+ char *ver, *type;
+ BIO *bio;
+ char buffer[15000];
+ buffer[0] = 0;
+
+ dprintf("Called");
+
+ if (statePtr->callback == (Tcl_Obj*)NULL)
+ return;
+
+ switch(version) {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(NO_SSL2) && !defined(OPENSSL_NO_SSL2)
+ case SSL2_VERSION:
+ ver = "SSLv2";
+ break;
+#endif
+#if !defined(NO_SSL3) && !defined(OPENSSL_NO_SSL3)
+ case SSL3_VERSION:
+ ver = "SSLv3";
+ break;
+#endif
+ case TLS1_VERSION:
+ ver = "TLSv1";
+ break;
+ case TLS1_1_VERSION:
+ ver = "TLSv1.1";
+ break;
+ case TLS1_2_VERSION:
+ ver = "TLSv1.2";
+ break;
+ case TLS1_3_VERSION:
+ ver = "TLSv1.3";
+ break;
+ case 0:
+ ver = "none";
+ break;
+ default:
+ ver = "unknown";
+ break;
+ }
+
+ switch (content_type) {
+ case SSL3_RT_HEADER:
+ type = "Header";
+ break;
+ case SSL3_RT_INNER_CONTENT_TYPE:
+ type = "Inner Content Type";
+ break;
+ case SSL3_RT_CHANGE_CIPHER_SPEC:
+ type = "Change Cipher";
+ break;
+ case SSL3_RT_ALERT:
+ type = "Alert";
+ break;
+ case SSL3_RT_HANDSHAKE:
+ type = "Handshake";
+ break;
+ case SSL3_RT_APPLICATION_DATA:
+ type = "App Data";
+ break;
+ case DTLS1_RT_HEARTBEAT:
+ type = "Heartbeat";
+ break;
+ default:
+ type = "unknown";
+ }
+
+ /* Needs compile time option "enable-ssl-trace". */
+ if ((bio = BIO_new(BIO_s_mem())) != NULL) {
+ int n;
+ SSL_trace(write_p, version, content_type, buf, len, ssl, (void *)bio);
+ n = BIO_read(bio, buffer, min(BIO_pending(bio), 14999));
+ n = (n<0) ? 0 : n;
+ buffer[n] = 0;
+ (void)BIO_flush(bio);
+ BIO_free(bio);
+ }
+
+ /* Create command to eval */
+ cmdPtr = Tcl_DuplicateObj(statePtr->callback);
+ Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj("message", -1));
+ Tcl_ListObjAppendElement(interp, cmdPtr,
+ Tcl_NewStringObj(Tcl_GetChannelName(statePtr->self), -1));
+ Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(write_p ? "Sent" : "Received", -1));
+ Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(ver, -1));
+ Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(type, -1));
+ Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(buffer, -1));
+
+ /* Eval callback command */
+ Tcl_IncrRefCount(cmdPtr);
+ EvalCallback(interp, statePtr, cmdPtr);
+ Tcl_DecrRefCount(cmdPtr);
+}
+#endif
+
+/*
+ *-------------------------------------------------------------------
+ *
* VerifyCallback --
*
* Monitors SSL certificate validation process. Used to control the
* behavior when the SSL_VERIFY_PEER flag is set. This is called
- * whenever a certificate is inspected or decided invalid.
+ * whenever a certificate is inspected or decided invalid. Called for
+ * each certificate in the cert chain.
*
* Checks:
* certificate chain is checked starting with the deepest nesting level
* (the root CA certificate) and worked upward to the peer's certificate.
* All signatures are valid, current time is within first and last validity time.
@@ -1421,10 +1538,18 @@
* SSL Callbacks
*/
SSL_set_app_data(statePtr->ssl, (void *)statePtr); /* point back to us */
SSL_set_verify(statePtr->ssl, verify, VerifyCallback);
SSL_set_info_callback(statePtr->ssl, InfoCallback);
+
+ /* Callback for observing protocol messages */
+#ifndef OPENSSL_NO_SSL_TRACE
+ /* void SSL_CTX_set_msg_callback_arg(statePtr->ctx, (void *)statePtr);
+ void SSL_CTX_set_msg_callback(statePtr->ctx, MessageCallback); */
+ SSL_set_msg_callback_arg(statePtr->ssl, (void *)statePtr);
+ SSL_set_msg_callback(statePtr->ssl, MessageCallback);
+#endif
/* Create Tcl_Channel BIO Handler */
statePtr->p_bio = BIO_new_tcl(statePtr, BIO_NOCLOSE);
statePtr->bio = BIO_new(BIO_f_ssl());