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 35
    internal defined BIO is 23) */
36 36
 #define BIO_TYPE_TLS_MBUF	(BIO_TYPE_SOURCE_SINK | 0xf2)
37 37
 
38
+/* debugging */
39
+#ifndef NO_TLS_BIO_DEBUG
40
+#define TLS_BIO_DEBUG
41
+#endif
42
+#ifdef TLS_BIO_DEBUG
43
+	#ifdef __SUNPRO_C
44
+		#define TLS_BIO_DBG(...) \
45
+			LOG_(DEFAULT_FACILITY, L_INFO, "tls_BIO: " LOC_INFO, __VA_ARGS__)
46
+	#else
47
+		#define TLS_BIO_DBG(fmt, args...) \
48
+			LOG_(DEFAULT_FACILITY, L_INFO, "tls_BIO: " LOC_INFO, fmt, ## args)
49
+	#endif /* __SUNPRO_c */
50
+#else /* TLS_BIO_DEBUG */
51
+	#ifdef __SUNPRO_C
52
+		#define TLS_BIO_DBG(...)
53
+	#else
54
+		#define TLS_BIO_DBG(fmt, args...)
55
+	#endif /* __SUNPRO_c */
56
+#endif /* TLS_BIO_DEBUG */
57
+
38 58
 
39 59
 static int tls_bio_mbuf_new(BIO* b);
40 60
 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 73
 {
74 74
 	BIO* ret;
75 75
 	
76
+	TLS_BIO_DBG("tls_BIO_new_mbuf called (%p, %p)\n", rd, wr);
76 77
 	ret = BIO_new(tls_BIO_mbuf());
77 78
 	if (unlikely(ret == 0))
78 79
 		return 0;
... ...
@@ -92,6 +115,7 @@ int tls_BIO_mbuf_set(BIO* b, struct tls_mbuf* rd, struct tls_mbuf* wr)
92 92
 {
93 93
 	struct tls_bio_mbuf_data* d;
94 94
 	
95
+	TLS_BIO_DBG("tls_BIO_muf_set called (%p, %p)\n", rd, wr);
95 96
 	if (unlikely(b->ptr == 0)){
96 97
 		BUG("null BIO ptr\n");
97 98
 		return 0;
... ...
@@ -113,6 +137,7 @@ static int tls_bio_mbuf_new(BIO* b)
113 113
 {
114 114
 	struct tls_bio_mbuf_data* d;
115 115
 	
116
+	TLS_BIO_DBG("tls_bio_mbuf_new called (%p)\n", b);
116 117
 	b->init = 0; /* not initialized yet */
117 118
 	b->num = 0;
118 119
 	b->ptr = 0;
... ...
@@ -134,6 +159,7 @@ static int tls_bio_mbuf_new(BIO* b)
134 134
  */
135 135
 static int tls_bio_mbuf_free(BIO* b)
136 136
 {
137
+	TLS_BIO_DBG("tls_bio_mbuf_free called (%p)\n", b);
137 138
 	if (unlikely( b == 0))
138 139
 			return 0;
139 140
 	if (likely(b->ptr)){
... ...
@@ -164,19 +190,30 @@ static int tls_bio_mbuf_read(BIO* b, char* dst, int dst_len)
164 164
 		if (unlikely(d == 0 || d->rd->buf == 0)) {
165 165
 			if (d == 0)
166 166
 				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);
167
+			else {
168
+				/* this form of calling read with a null buffer is used
169
+				   as a shortcut when no data is available =>
170
+				   simulate EAGIAN/WANT_READ */
171
+				TLS_BIO_DBG("read (%p, %p, %d) called with null read buffer"
172
+						" => simulating EAGAIN/WANT_READ\n", b, dst, dst_len);
173
+				BIO_set_retry_read(b);
174
+			}
169 175
 			return -1;
170 176
 		}
171 177
 		rd = d->rd;
172 178
 		if (unlikely(rd->used == rd->pos && dst_len)) {
173 179
 			/* mimic non-blocking read behaviour */
180
+			TLS_BIO_DBG("read (%p, %p, %d) called with full rd (%d)"
181
+						" => simulating EAGAIN/WANT_READ\n",
182
+						b, dst, dst_len, rd->used);
174 183
 			BIO_set_retry_read(b);
175 184
 			return -1;
176 185
 		}
177 186
 		ret = MIN_int(rd->used - rd->pos, dst_len);
178 187
 		/* copy data from rd.buf into dst */
179
-		memcpy(rd->buf+rd->pos, dst, ret);
188
+		memcpy(dst, rd->buf+rd->pos, ret);
189
+		TLS_BIO_DBG("read(%p, %p, %d) called with rd=%p pos=%d => %d bytes\n",
190
+						b, dst, dst_len, rd->buf, rd->pos, ret);
180 191
 		rd->pos += ret;
181 192
 /*		if (unlikely(rd->pos < rd->used))
182 193
 			BIO_set_retry_read(b);
... ...
@@ -204,13 +241,21 @@ static int tls_bio_mbuf_write(BIO* b, const char* src, int src_len)
204 204
 	if (unlikely(d == 0 || d->wr->buf == 0)) {
205 205
 		if (d == 0)
206 206
 			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);
207
+		else {
208
+			/* this form of calling write with a null buffer is used
209
+			   as a shortcut when no data is available =>
210
+			   simulate EAGAIN/WANT_WRITE */
211
+			TLS_BIO_DBG("write (%p, %p, %d) called with null buffer"
212
+					" => simulating WANT_WRITE\n", b, src, src_len);
213
+			BIO_set_retry_write(b);
214
+		}
209 215
 		return -1;
210 216
 	}
211 217
 	wr = d->wr;
212 218
 	if (unlikely(wr->size == wr->used && src_len)) {
213 219
 		/* mimic non-blocking socket behaviour */
220
+		TLS_BIO_DBG("write (%p, %p, %d) called with full wr buffer (%d)"
221
+					" => simulating WANT_WRITE\n", b, src, src_len, wr->used);
214 222
 		BIO_set_retry_write(b);
215 223
 		return -1;
216 224
 	}
... ...
@@ -220,6 +265,7 @@ static int tls_bio_mbuf_write(BIO* b, const char* src, int src_len)
220 220
 /*	if (unlikely(ret < src_len))
221 221
 		BIO_set_retry_write();
222 222
 */
223
+	TLS_BIO_DBG("write called (%p, %p, %d) => %d\n", b, src, src_len, ret);
223 224
 	return ret;
224 225
 }
225 226
 
... ...
@@ -227,8 +273,34 @@ static int tls_bio_mbuf_write(BIO* b, const char* src, int src_len)
227 227
 
228 228
 static long tls_bio_mbuf_ctrl(BIO* b, int cmd, long arg1, void* arg2)
229 229
 {
230
-	/* no cmd supported */
231
-	return 0;
230
+	long ret;
231
+	ret=0;
232
+	switch(cmd) {
233
+		case BIO_C_SET_FD:
234
+		case BIO_C_GET_FD:
235
+			ret = -1; /* error, not supported */
236
+			break;
237
+		case BIO_CTRL_GET_CLOSE:
238
+		case BIO_CTRL_SET_CLOSE:
239
+			ret = 0;
240
+			break;
241
+		case BIO_CTRL_DUP:
242
+		case BIO_CTRL_FLUSH:
243
+			ret = 1;
244
+			break;
245
+		case BIO_CTRL_RESET:
246
+		case BIO_C_FILE_SEEK:
247
+		case BIO_C_FILE_TELL:
248
+		case BIO_CTRL_INFO:
249
+		case BIO_CTRL_PENDING:
250
+		case BIO_CTRL_WPENDING:
251
+		default:
252
+			ret = 0;
253
+			break;
254
+	}
255
+	TLS_BIO_DBG("ctrl called (%p, %d, %ld, %p) => %ld\n",
256
+				b, cmd, arg1, arg2, ret);
257
+	return ret;
232 258
 }
233 259
 
234 260
 
... ...
@@ -237,6 +309,7 @@ static int tls_bio_mbuf_puts(BIO* b, const char* s)
237 237
 {
238 238
 	int len;
239 239
 	
240
+	TLS_BIO_DBG("puts called (%p, %s)\n", b, s);
240 241
 	len=strlen(s);
241 242
 	return tls_bio_mbuf_write(b, s, len);
242 243
 }
... ...
@@ -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: */