1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
+
-
+
-
-
-
-
-
-
-
-
|
/*
* Copyright (C) 1997-2000 Matt Newman <[email protected]>
* Copyright (C) 2000 Ajuba Solutions
*
* $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsIO.c,v 1.9 2000/08/15 00:02:08 hobbs Exp $
* $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsIO.c,v 1.10 2000/08/15 18:49:30 hobbs Exp $
*
* TLS (aka SSL) Channel - can be layered on any bi-directional
* Tcl_Channel (Note: Requires Trf Core Patch)
*
* This was built from scratch based upon observation of OpenSSL 0.9.2B
*
* Addition credit is due for Andreas Kupries ([email protected]), for
* providing the Tcl_ReplaceChannel mechanism and working closely with me
* to enhance it to support full fileevent semantics.
*
* Also work done by the follow people provided the impetus to do this "right":
* tclSSL (Colin McCormack, Shared Technology)
* SSLtcl (Peter Antman)
*
*/
#include "tlsInt.h"
/*
* External functions
*/
/*
* Local Defines
*/
/*
* Forward declarations
*/
static int TlsBlockModeProc _ANSI_ARGS_((ClientData instanceData,
int mode));
static int TlsCloseProc _ANSI_ARGS_ ((ClientData instanceData,
|
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
|
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
int mask));
static void TlsChannelHandler _ANSI_ARGS_ ((ClientData clientData,
int mask));
static void TlsChannelHandlerTimer _ANSI_ARGS_ ((ClientData clientData));
/*
* This structure describes the channel type structure for TCP socket
* based IO:
* based IO. These are what the structures should look like, but we
* have to build them up at runtime to be correct depending on whether
* we are loaded into an 8.2.0-8.3.1 or 8.3.2+ Tcl interpreter.
*/
#ifdef TLS_STATIC_STRUCTURES_NOT_USED
static Tcl_ChannelType tlsChannelType2 = {
"tls", /* Type name. */
#ifndef TCL_CHANNEL_VERSION_2
/*
* Avoids warning in Windows compiler when compiling with 8.3.1-.
*/
(Tcl_DriverBlockModeProc *)
#endif
TCL_CHANNEL_VERSION_2, /* A v2 channel (8.3.2+) */
TlsCloseProc, /* Close proc. */
TlsInputProc, /* Input proc. */
TlsOutputProc, /* Output proc. */
NULL, /* Seek proc. */
NULL, /* Set option proc. */
TlsGetOptionProc, /* Get option proc. */
TlsWatchProc, /* Initialize notifier. */
TlsGetHandleProc, /* Get file handle out of channel. */
NULL, /* Close2Proc. */
TlsBlockModeProc, /* Set blocking/nonblocking mode.*/
NULL, /* FlushProc. */
TlsNotifyProc, /* handlerProc. */
};
static Tcl_ChannelType tlsChannelType1 = {
"tls", /* Type name. */
#ifdef TCL_CHANNEL_VERSION_2
/*
* Avoids warning in Windows compiler when compiling with 8.3.2+.
*/
(Tcl_ChannelTypeVersion)
#endif
TlsBlockModeProc, /* Set blocking/nonblocking mode.*/
TlsCloseProc, /* Close proc. */
TlsInputProc, /* Input proc. */
TlsOutputProc, /* Output proc. */
NULL, /* Seek proc. */
NULL, /* Set option proc. */
TlsGetOptionProc, /* Get option proc. */
TlsWatchProc, /* Initialize notifier. */
TlsGetHandleProc, /* Get file handle out of channel. */
};
#else
static Tcl_ChannelType *tlsChannelType = NULL;
#endif
/*
*-------------------------------------------------------------------
*
* Tls_ChannelType --
*
* Return the correct TLS channel driver info
*
* Results:
* The correct channel driver for the current version of Tcl.
*
* Side effects:
* None.
*
*-------------------------------------------------------------------
*/
Tcl_ChannelType *Tls_ChannelType()
{
/*
* Initialize the channel type if necessary
*/
if (tlsChannelType == NULL) {
/*
* Allocation of a new channeltype structure is not easy, because of
* the various verson of the core and subsequent changes to the
* structure. The main challenge is to allocate enough memory for
* odern versions even if this extyension is compiled against one
* of the older variant!
*
* (1) Versions before stubs (8.0.x) are simple, because they are
* supported only if the extension is compiled against exactly
* that version of the core.
*
* (2) With stubs we just determine the difference between the older
* and modern variant and overallocate accordingly if compiled
* against an older variant.
*/
int size = sizeof(Tcl_ChannelType); /* Base size */
/*
* Size of a procedure pointer. We assume that all procedure
* pointers are of the same size, regardless of exact type
* (arguments and return values).
*
* 8.2. First version containing close2proc. Baseline.
* 8.3.2 Three additional vectors. Moved blockMode, new flush- and
* handlerProc's.
*
* => Compilation against earlier version has to overallocate three
* procedure pointers.
*/
#ifdef EMULATE_CHANNEL_VERSION_2
size += 3 * procPtrSize;
#endif
tlsChannelType = (Tcl_ChannelType *) ckalloc(size);
memset((VOID *) tlsChannelType, 0, size);
/*
* Common elements of the structure (no changes in location or name)
* close2Proc, seekProc, setOptionProc stay NULL.
*/
tlsChannelType->closeProc = TlsCloseProc;
tlsChannelType->inputProc = TlsInputProc;
tlsChannelType->outputProc = TlsOutputProc;
tlsChannelType->getOptionProc = TlsGetOptionProc;
tlsChannelType->watchProc = TlsWatchProc;
tlsChannelType->getHandleProc = TlsGetHandleProc;
/*
* blockModeProc is a twister. We have to make some runtime-choices,
* depending on the version we compiled against.
*/
#ifdef EMULATE_CHANNEL_VERSION_2
/*
* We are compiling against an 8.3.1- core. We have to create some
* definitions for the new elements as the compiler does not know them
* by name.
*/
if (channelTypeVersion == TLS_CHANNEL_VERSION_2) {
return &tlsChannelType2;
} else {
return &tlsChannelType1;
}
if (channelTypeVersion == TLS_CHANNEL_VERSION_1) {
/*
* The 'version' element of 8.3.2 is in the the place of the
* blockModeProc. For 8.2.0-8.3.1 we have to set our blockModeProc
* into this place.
*/
tlsChannelType->blockModeProc = TlsBlockModeProc;
} else /* channelTypeVersion == TLS_CHANNEL_VERSION_2 */ {
/*
* For the 8.3.2 core we present ourselves as a version 2
* driver. This means a special value in version (ex
* blockModeProc), blockModeProc in a different place and of
* course usage of the handlerProc. The last two have to
* referenced with pointer magic because they aren't defined
* otherwise.
*/
tlsChannelType->blockModeProc =
(Tcl_DriverBlockModeProc*) TLS_CHANNEL_VERSION_2;
(*((Tcl_DriverBlockModeProc**)(&(tlsChannelType->close2Proc)+1)))
= TlsBlockModeProc;
(*((TlsDriverHandlerProc**)(&(tlsChannelType->close2Proc)+3)))
= TlsNotifyProc;
}
#else
/*
* Compiled against 8.3.2+. Direct access to all elements possible. Use
* channelTypeVersion information to select the values to use.
*/
if (channelTypeVersion == TLS_CHANNEL_VERSION_1) {
/*
* The 'version' element of 8.3.2 is in the the place of the
* blockModeProc. For the original patch in 8.1.x and the firstly
* included (8.2) we have to set our blockModeProc into this
* place.
*/
tlsChannelType->version = (Tcl_ChannelTypeVersion)TlsBlockModeProc;
} else /* channelTypeVersion == TLS_CHANNEL_VERSION_2 */ {
/*
* For the 8.3.2 core we present ourselves as a version 2
* driver. This means a special value in version (ex
* blockModeProc), blockModeProc in a different place and of
* course usage of the handlerProc.
*/
tlsChannelType->version = TCL_CHANNEL_VERSION_2;
tlsChannelType->blockModeProc = TlsBlockModeProc;
tlsChannelType->handlerProc = TlsNotifyProc;
}
#endif
}
return tlsChannelType;
}
/*
*-------------------------------------------------------------------
*
* TlsBlockModeProc --
*
|