Browse code

tls: tls_bio ctrl cmd support, fixes and debug

- proper return code for some BIO_ctrl commands used internally by SSL_*.
(BIO_CTRL_DUP, BIO_CTRL_FLUSH)
- when the attached memory buffer is null and read or write is
attempted, behave similar to socket bio on EAGAIN
(BIO_set_retry_read(b)).
- fixed tls_bio_mbuf_read bug (switched params in memcpy).
- added tls_mbuf_init(...)
- extended debug messages if TLS_BIO_DEBUG is defined.

Andrei Pelinescu-Onciul authored on 20/05/2010 15:44:13
Showing 2 changed files
... ...
@@ -24,6 +24,8 @@
24 24
  * History:
25 25
  * --------
26 26
  *  2010-03-25  initial version (andrei)
27
+ *  2010-05-20  emulate EAGAIN on null rd/wr memory buffer; handle some
28
+ *              needed commands in ctrl; debug support (TLS_BIO_DBG) (andrei)
27 29
 */
28 30
 
29 31
 #include "tls_bio.h"
... ...
@@ -35,6 +37,26 @@
35 37
    internal defined BIO is 23) */
36 38
 #define BIO_TYPE_TLS_MBUF	(BIO_TYPE_SOURCE_SINK | 0xf2)
37 39
 
40
+/* debugging */
41
+#ifndef NO_TLS_BIO_DEBUG
42
+#define TLS_BIO_DEBUG
43
+#endif
44
+#ifdef TLS_BIO_DEBUG
45
+	#ifdef __SUNPRO_C
46
+		#define TLS_BIO_DBG(...) \
47
+			LOG_(DEFAULT_FACILITY, L_INFO, "tls_BIO: " LOC_INFO, __VA_ARGS__)
48
+	#else
49
+		#define TLS_BIO_DBG(fmt, args...) \
50
+			LOG_(DEFAULT_FACILITY, L_INFO, "tls_BIO: " LOC_INFO, fmt, ## args)
51
+	#endif /* __SUNPRO_c */
52
+#else /* TLS_BIO_DEBUG */
53
+	#ifdef __SUNPRO_C
54
+		#define TLS_BIO_DBG(...)
55
+	#else
56
+		#define TLS_BIO_DBG(fmt, args...)
57
+	#endif /* __SUNPRO_c */
58
+#endif /* TLS_BIO_DEBUG */
59
+
38 60
 
39 61
 static int tls_bio_mbuf_new(BIO* b);
40 62
 static int tls_bio_mbuf_free(BIO* b);
... ...
@@ -73,6 +95,7 @@ BIO* tls_BIO_new_mbuf(struct tls_mbuf* rd, struct tls_mbuf* wr)
73 95
 {
74 96
 	BIO* ret;
75 97
 	
98
+	TLS_BIO_DBG("tls_BIO_new_mbuf called (%p, %p)\n", rd, wr);
76 99
 	ret = BIO_new(tls_BIO_mbuf());
77 100
 	if (unlikely(ret == 0))
78 101
 		return 0;
... ...
@@ -92,6 +115,7 @@ int tls_BIO_mbuf_set(BIO* b, struct tls_mbuf* rd, struct tls_mbuf* wr)
92 115
 {
93 116
 	struct tls_bio_mbuf_data* d;
94 117
 	
118
+	TLS_BIO_DBG("tls_BIO_muf_set called (%p, %p)\n", rd, wr);
95 119
 	if (unlikely(b->ptr == 0)){
96 120
 		BUG("null BIO ptr\n");
97 121
 		return 0;
... ...
@@ -113,6 +137,7 @@ static int tls_bio_mbuf_new(BIO* b)
113 137
 {
114 138
 	struct tls_bio_mbuf_data* d;
115 139
 	
140
+	TLS_BIO_DBG("tls_bio_mbuf_new called (%p)\n", b);
116 141
 	b->init = 0; /* not initialized yet */
117 142
 	b->num = 0;
118 143
 	b->ptr = 0;
... ...
@@ -134,6 +159,7 @@ static int tls_bio_mbuf_new(BIO* b)
134 159
  */
135 160
 static int tls_bio_mbuf_free(BIO* b)
136 161
 {
162
+	TLS_BIO_DBG("tls_bio_mbuf_free called (%p)\n", b);
137 163
 	if (unlikely( b == 0))
138 164
 			return 0;
139 165
 	if (likely(b->ptr)){
... ...
@@ -164,19 +190,30 @@ static int tls_bio_mbuf_read(BIO* b, char* dst, int dst_len)
164 190
 		if (unlikely(d == 0 || d->rd->buf == 0)) {
165 191
 			if (d == 0)
166 192
 				BUG("tls_BIO_mbuf %p: read called with null b->ptr\n", b);
167
-			else
168
-				BUG("tls_BIO_mbuf %p: read called with null read buffer\n", b);
193
+			else {
194
+				/* this form of calling read with a null buffer is used
195
+				   as a shortcut when no data is available =>
196
+				   simulate EAGIAN/WANT_READ */
197
+				TLS_BIO_DBG("read (%p, %p, %d) called with null read buffer"
198
+						" => simulating EAGAIN/WANT_READ\n", b, dst, dst_len);
199
+				BIO_set_retry_read(b);
200
+			}
169 201
 			return -1;
170 202
 		}
171 203
 		rd = d->rd;
172 204
 		if (unlikely(rd->used == rd->pos && dst_len)) {
173 205
 			/* mimic non-blocking read behaviour */
206
+			TLS_BIO_DBG("read (%p, %p, %d) called with full rd (%d)"
207
+						" => simulating EAGAIN/WANT_READ\n",
208
+						b, dst, dst_len, rd->used);
174 209
 			BIO_set_retry_read(b);
175 210
 			return -1;
176 211
 		}
177 212
 		ret = MIN_int(rd->used - rd->pos, dst_len);
178 213
 		/* copy data from rd.buf into dst */
179
-		memcpy(rd->buf+rd->pos, dst, ret);
214
+		memcpy(dst, rd->buf+rd->pos, ret);
215
+		TLS_BIO_DBG("read(%p, %p, %d) called with rd=%p pos=%d => %d bytes\n",
216
+						b, dst, dst_len, rd->buf, rd->pos, ret);
180 217
 		rd->pos += ret;
181 218
 /*		if (unlikely(rd->pos < rd->used))
182 219
 			BIO_set_retry_read(b);
... ...
@@ -204,13 +241,21 @@ static int tls_bio_mbuf_write(BIO* b, const char* src, int src_len)
204 241
 	if (unlikely(d == 0 || d->wr->buf == 0)) {
205 242
 		if (d == 0)
206 243
 			BUG("tls_BIO_mbuf %p: write called with null b->ptr\n", b);
207
-		else
208
-			BUG("tls_BIO_mbuf %p: write called with null read buffer\n", b);
244
+		else {
245
+			/* this form of calling write with a null buffer is used
246
+			   as a shortcut when no data is available =>
247
+			   simulate EAGAIN/WANT_WRITE */
248
+			TLS_BIO_DBG("write (%p, %p, %d) called with null buffer"
249
+					" => simulating WANT_WRITE\n", b, src, src_len);
250
+			BIO_set_retry_write(b);
251
+		}
209 252
 		return -1;
210 253
 	}
211 254
 	wr = d->wr;
212 255
 	if (unlikely(wr->size == wr->used && src_len)) {
213 256
 		/* mimic non-blocking socket behaviour */
257
+		TLS_BIO_DBG("write (%p, %p, %d) called with full wr buffer (%d)"
258
+					" => simulating WANT_WRITE\n", b, src, src_len, wr->used);
214 259
 		BIO_set_retry_write(b);
215 260
 		return -1;
216 261
 	}
... ...
@@ -220,6 +265,7 @@ static int tls_bio_mbuf_write(BIO* b, const char* src, int src_len)
220 265
 /*	if (unlikely(ret < src_len))
221 266
 		BIO_set_retry_write();
222 267
 */
268
+	TLS_BIO_DBG("write called (%p, %p, %d) => %d\n", b, src, src_len, ret);
223 269
 	return ret;
224 270
 }
225 271
 
... ...
@@ -227,8 +273,34 @@ static int tls_bio_mbuf_write(BIO* b, const char* src, int src_len)
227 273
 
228 274
 static long tls_bio_mbuf_ctrl(BIO* b, int cmd, long arg1, void* arg2)
229 275
 {
230
-	/* no cmd supported */
231
-	return 0;
276
+	long ret;
277
+	ret=0;
278
+	switch(cmd) {
279
+		case BIO_C_SET_FD:
280
+		case BIO_C_GET_FD:
281
+			ret = -1; /* error, not supported */
282
+			break;
283
+		case BIO_CTRL_GET_CLOSE:
284
+		case BIO_CTRL_SET_CLOSE:
285
+			ret = 0;
286
+			break;
287
+		case BIO_CTRL_DUP:
288
+		case BIO_CTRL_FLUSH:
289
+			ret = 1;
290
+			break;
291
+		case BIO_CTRL_RESET:
292
+		case BIO_C_FILE_SEEK:
293
+		case BIO_C_FILE_TELL:
294
+		case BIO_CTRL_INFO:
295
+		case BIO_CTRL_PENDING:
296
+		case BIO_CTRL_WPENDING:
297
+		default:
298
+			ret = 0;
299
+			break;
300
+	}
301
+	TLS_BIO_DBG("ctrl called (%p, %d, %ld, %p) => %ld\n",
302
+				b, cmd, arg1, arg2, ret);
303
+	return ret;
232 304
 }
233 305
 
234 306
 
... ...
@@ -237,6 +309,7 @@ static int tls_bio_mbuf_puts(BIO* b, const char* s)
237 309
 {
238 310
 	int len;
239 311
 	
312
+	TLS_BIO_DBG("puts called (%p, %s)\n", b, s);
240 313
 	len=strlen(s);
241 314
 	return tls_bio_mbuf_write(b, s, len);
242 315
 }
... ...
@@ -34,9 +34,9 @@
34 34
 /* memory buffer used for tls I/O */
35 35
 struct tls_mbuf {
36 36
 	unsigned char* buf;
37
-	int pos;  /* current position in the buffer while reading*/
38
-	int used; /* how much it's used */
39
-	int size; /* total buffer size (fixed) */
37
+	int pos;  /**< current position in the buffer while reading or writing*/
38
+	int used; /**< how much it's used  (read or write)*/
39
+	int size; /**< total buffer size (fixed) */
40 40
 };
41 41
 
42 42
 struct tls_bio_mbuf_data {
... ...
@@ -49,6 +49,24 @@ BIO_METHOD* tls_BIO_mbuf(void);
49 49
 BIO* tls_BIO_new_mbuf(struct tls_mbuf* rd, struct tls_mbuf* wr);
50 50
 int tls_BIO_mbuf_set(BIO* b, struct tls_mbuf* rd, struct tls_mbuf* wr);
51 51
 
52
+
53
+
54
+/** intialize an mbuf structure.
55
+ * @param mb - struct tls_mbuf pointer that will be intialized.
56
+ * @param b  - buffer (unsigned char*).
57
+ * @param sz - suze of the buffer (int).
58
+ * WARNING: the buffer will not be copied, but referenced.
59
+ */
60
+#define tls_mbuf_init(mb, b, sz) \
61
+	do { \
62
+		(mb)->buf = (b); \
63
+		(mb)->size = (sz); \
64
+		(mb)->pos = 0; \
65
+		(mb)->used = 0; \
66
+	} while(0)
67
+
68
+
69
+
52 70
 #endif /*__tls_bio_h*/
53 71
 
54 72
 /* vi: set ts=4 sw=4 tw=79:ai:cindent: */