Check-in [6252a3a1f5]
Overview
Comment:Added IO buffer checks to TlsChannelHandlerTimer mask function. Reordered TlsNotifyProc to check conditions prior to timer deletion. Pass buffer length in MessageCallback.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | main
Files: files | file ages | folders
SHA3-256: 6252a3a1f56de1c69f993bbaa539efd0f3c32a60070ae163cea62471a81895d5
User & Date: bohagan on 2024-12-29 04:36:20
Other Links: branch diff | manifest | tags
Context
2024-12-31
04:12
More comment updates and changes for fast path option check-in: c61a46b561 user: bohagan tags: trunk, main
2024-12-29
04:36
Added IO buffer checks to TlsChannelHandlerTimer mask function. Reordered TlsNotifyProc to check conditions prior to timer deletion. Pass buffer length in MessageCallback. check-in: 6252a3a1f5 user: bohagan tags: trunk, main
04:18
Renamed BIO read/write functions to input/output to avoid confusion with API names. Added PKI and Certificates section to docs. Added/updated comments, formatting updates, etc. check-in: 3848af25d2 user: bohagan tags: trunk, main
Changes
227
228
229
230
231
232
233

234
235
236
237
238
239
240
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241







+







{
    State *statePtr = (State*)arg;
    Tcl_Interp *interp	= statePtr->interp;
    Tcl_Obj *cmdPtr;
    char *ver, *type;
    BIO *bio;
    char buffer[15000];
    Tcl_Size blen = 0;
    buffer[0] = 0;

    dprintf("Called");

    if (statePtr->callback == (Tcl_Obj*)NULL) {
	return;
    }
296
297
298
299
300
301
302
303
304
305
306
307



308
309
310
311
312
313
314
315
316
317
318
319
320
321
322

323
324
325
326
327
328
329
297
298
299
300
301
302
303

304



305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321

322
323
324
325
326
327
328
329







-

-
-
-
+
+
+














-
+







#endif
    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, BIO_pending(bio) < 15000 ? BIO_pending(bio) : 14999);
	n = (n<0) ? 0 : n;
	buffer[n] = 0;
	blen = (Tcl_Size) BIO_read(bio, buffer, BIO_pending(bio) < 15000 ? BIO_pending(bio) : 14999);
	blen = (blen<0) ? 0 : blen;
	buffer[blen] = 0;
	(void)BIO_flush(bio);
	BIO_free(bio);
   }

    dprintf("Message direction=%d, ver=%s, type=%s, message=%s", write_p, ver, type, &buffer[0]);

    /* Create command to eval with fn, chan, direction, version, type, and message args */
    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));
    Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(buffer, blen));

    /* Eval callback command */
    Tcl_IncrRefCount(cmdPtr);
    EvalCallback(interp, statePtr, cmdPtr);
    Tcl_DecrRefCount(cmdPtr);
}
#endif
2564
2565
2566
2567
2568
2569
2570
2571

2572
2573
2574
2575
2576
2577
2578
2564
2565
2566
2567
2568
2569
2570

2571
2572
2573
2574
2575
2576
2577
2578







-
+







	/* connection state */
	LAPPEND_STR(interp, objPtr, "state", SSL_state_string_long(ssl), -1);

	/* Get SNI requested server name */
	LAPPEND_STR(interp, objPtr, "servername", SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name), -1);

	/* Report the selected protocol as a result of the negotiation */
	SSL_get0_alpn_selected(statePtr->ssl, &proto, &ulen);
	SSL_get0_alpn_selected(ssl, &proto, &ulen);
	LAPPEND_STR(interp, objPtr, "alpn", (char *)proto, (Tcl_Size) ulen);

	/* Get protocol */
	LAPPEND_STR(interp, objPtr, "protocol", SSL_get_version(ssl), -1);

	/* Renegotiation allowed */
	LAPPEND_BOOL(interp, objPtr, "renegotiation_allowed", SSL_get_secure_renegotiation_support((SSL *) ssl));
3100
3101
3102
3103
3104
3105
3106
3107

3108
3109
3110
3111

3112
3113
3114
3115
3116
3117
3118
3100
3101
3102
3103
3104
3105
3106

3107
3108
3109
3110

3111
3112
3113
3114
3115
3116
3117
3118







-
+



-
+








    /* Remove list of ALPN protocols */
    if (statePtr->protos) {
	ckfree(statePtr->protos);
	statePtr->protos = NULL;
    }

    /* BIO_free_all() frees up an entire BIO chain */
    /* BIO_free() frees up a single BIO */
    if (statePtr->bio) {
	/* This will call SSL_shutdown. Bug 1414045 */
	dprintf("BIO_free(%p)", statePtr->bio);
	BIO_free_all(statePtr->bio);
	BIO_free(statePtr->bio);
	statePtr->bio = NULL;
    }

    /* Free SSL context and statePtr->p_bio  */
    if (statePtr->ssl) {
	dprintf("SSL_free(%p) and p_bio(%p)", statePtr->ssl, statePtr->p_bio);
	SSL_free(statePtr->ssl);
982
983
984
985
986
987
988
989

990
991
992
993
994


995
996
997
998
999
1000
1001


1002
1003
1004
1005
1006
1007
1008


1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
982
983
984
985
986
987
988

989
990
991
992


993
994
995
996
997
998
999


1000
1001
1002
1003
1004
1005
1006


1007
1008
1009
1010



1011
1012
1013
1014
1015
1016
1017







-
+



-
-
+
+





-
-
+
+





-
-
+
+


-
-
-







 */
static void TlsChannelHandlerTimer(
    ClientData clientData)	/* Socket state. */
{
    State *statePtr = (State *) clientData;
    int mask = statePtr->want; /* Init to SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE */

    dprintf("Called");
    dprintf("Called with mask 0x%02x", mask);

    statePtr->timer = (Tcl_TimerToken) NULL;

    /* Check for amount of data pending in BIO write buffer */
    if (BIO_wpending(statePtr->bio)) {
    /* Check for amount of data pending in IO or BIO write buffer */
    if (Tcl_OutputBuffered(statePtr->self) || BIO_wpending(statePtr->bio)) {
	dprintf("[chan=%p] BIO writable", statePtr->self);

	mask |= TCL_WRITABLE;
    }

    /* Check for amount of data pending in BIO read buffer */
    if (BIO_pending(statePtr->bio)) {
    /* Check for amount of data pending in IO or BIO read buffer */
    if (Tcl_InputBuffered(statePtr->self) || BIO_pending(statePtr->bio)) {
	dprintf("[chan=%p] BIO readable", statePtr->self);

	mask |= TCL_READABLE;
    }

    /* Notify the generic IO layer that the mask events have occurred on the channel */
    dprintf("Notifying ourselves");
    /* Notify the generic IO layer that mask events have occurred on the channel */
    dprintf("Notifying ourselves with mask=%d", mask);
    Tcl_NotifyChannel(statePtr->self, mask);
    statePtr->want = 0;

    dprintf("Returning");

    return;
}

/*
 *-----------------------------------------------------------------------------
 *
 * TlsWatchProc --
1079
1080
1081
1082
1083
1084
1085
1086

1087
1088

1089
1090
1091
1092
1093
1094
1095
1076
1077
1078
1079
1080
1081
1082

1083
1084

1085
1086
1087
1088
1089
1090
1091
1092







-
+

-
+







    watchProc(Tcl_GetChannelInstanceData(parent), mask);

    /* Do we have any pending events */
    pending = (statePtr->want || \
	((mask & TCL_READABLE) && ((Tcl_InputBuffered(statePtr->self) > 0) || (BIO_ctrl_pending(statePtr->bio) > 0))) ||
	((mask & TCL_WRITABLE) && ((Tcl_OutputBuffered(statePtr->self) > 0) || (BIO_ctrl_wpending(statePtr->bio) > 0))));

    dprintf("IO Want=%d, input buffer=%d, output buffer=%d, BIO pending=%zd, BIO wpending=%zd", \
    dprintf("IO Want=%d, input buffer=%d, output buffer=%d, BIO pending=%zd, BIO wpending=%zd, pending=%d", \
	statePtr->want, Tcl_InputBuffered(statePtr->self), Tcl_OutputBuffered(statePtr->self), \
	BIO_ctrl_pending(statePtr->bio), BIO_ctrl_wpending(statePtr->bio));
	BIO_ctrl_pending(statePtr->bio), BIO_ctrl_wpending(statePtr->bio), pending);

    if (!(mask & TCL_READABLE) || pending == 0) {
	/* Remove timer, if any */
	if (statePtr->timer != (Tcl_TimerToken) NULL) {
	    dprintf("A timer was found, deleting it");
	    Tcl_DeleteTimerHandler(statePtr->timer);
	    statePtr->timer = (Tcl_TimerToken) NULL;
1153
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174


1175
1176
1177
1178
1179
1180
1181
1150
1151
1152
1153
1154
1155
1156

1157
1158













1159
1160
1161
1162
1163
1164
1165
1166
1167







-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+







    ClientData instanceData,	/* Socket state. */
    int mask)			/* type of event that occurred: OR-ed
				 * combination of TCL_READABLE or TCL_WRITABLE */
{
    State *statePtr = (State *) instanceData;
    int errorCode = 0;

    dprintf("Called");
    dprintf("Called with mask 0x%02x", mask);

    /*
     * Delete an existing timer. It was not fired, yet we are
     * here, so the channel below generated such an event and we
     * don't have to. The renewal of the interest after the
     * execution of channel handlers will eventually cause us to
     * recreate the timer (in WatchProc).
     */
    if (statePtr->timer != (Tcl_TimerToken) NULL) {
	Tcl_DeleteTimerHandler(statePtr->timer);
	statePtr->timer = (Tcl_TimerToken) NULL;
    }

    /* Skip if user verify callback is still running */
    /* Abort if the user verify callback is still running to avoid triggering
     * another call before the current one is complete. */
    if (statePtr->flags & TLS_TCL_CALLBACK) {
	dprintf("Callback is on-going, returning failed");
	return 0;
    }

    /* If not initialized, do connect */
    if (statePtr->flags & TLS_TCL_INIT) {
1192
1193
1194
1195
1196
1197
1198
1199
1200











1201
1202
1203


1204
1205

1206
1207
1208
1209
1210
1211
1212
1178
1179
1180
1181
1182
1183
1184


1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196


1197
1198

1199
1200
1201
1202
1203
1204
1205
1206
1207







-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
-

+







		return 0;
	    }

	    dprintf("Tls_WaitForConnect returned an error");
	}
    }

    dprintf("Returning %i", mask);

    /*
     * Delete an existing timer. It was not fired, yet we are here, so the
     * channel below generated such an event and we don't have to. The renewal
     * of the interest after the execution of channel handlers will eventually
     * cause us to recreate the timer (in WatchProc).
     */
    if (statePtr->timer != (Tcl_TimerToken) NULL) {
	Tcl_DeleteTimerHandler(statePtr->timer);
	statePtr->timer = (Tcl_TimerToken) NULL;
    }

    /*
     * An event occurred in the underlying channel.  This
     * transformation doesn't process such events thus returns the
     * An event occurred in the underlying channel. This transformation doesn't
     * process such events thus returns the incoming mask unchanged.
     * incoming mask unchanged.
     */
    dprintf("Returning %i", mask);
    return mask;
}

/*
 *-----------------------------------------------------------------------------
 *
 * Tls_ChannelType --