]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/bio/bss_bio.c
cae59170361646252c4e3fb06966d481f9ac9fdc
[thirdparty/openssl.git] / crypto / bio / bss_bio.c
1 /* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */
2
3 /* *** Not yet finished (or even tested). *** */
4
5 /* Special method for a BIO where the other endpoint is also a BIO
6 * of this kind, handled by the same thread.
7 * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces
8 * for which no specific BIO method is available. */
9
10 #include <assert.h>
11 #include <stdlib.h>
12
13 #include <openssl/bio.h>
14 #include <openssl/err.h>
15 #include <openssl/crypto.h>
16
17 static int bio_new(BIO *bio);
18 static int bio_free(BIO *bio);
19 static int bio_read(BIO *bio, char *buf, int size);
20 static int bio_write(BIO *bio, char *buf, int num);
21 static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr);
22 static int bio_puts(BIO *bio, char *str);
23
24 static int bio_make_pair(BIO *bio1, BIO *bio2);
25 static void bio_destroy_pair(BIO *bio);
26
27 static BIO_METHOD methods_biop =
28 {
29 BIO_TYPE_BIO,
30 "BIO pair",
31 bio_write,
32 bio_read,
33 bio_puts,
34 NULL /* no bio_gets */,
35 bio_ctrl,
36 bio_new,
37 bio_free
38 };
39
40 BIO_METHOD *BIO_s_bio(void)
41 {
42 return &methods_biop;
43 }
44
45 struct bio_bio_st
46 {
47 BIO *peer; /* NULL if buf == NULL.
48 * If peer != NULL, then peer->ptr is also a bio_bio_st,
49 * and its "peer" member points back to us.
50 * peer != NULL iff init != 0 in the BIO. */
51
52 /* This is for what we write (i.e. reading uses peer's struct): */
53 int closed; /* valid iff peer != NULL */
54 size_t len; /* valid iff buf != NULL; 0 if peer == NULL */
55 size_t offset; /* valid iff buf != NULL; 0 if len == 0 */
56 size_t size;
57 char *buf; /* "size" elements (if != NULL) */
58
59 size_t request; /* valid iff peer != NULL; 0 if len != 0;
60 * otherwise set by peer to number of bytes
61 * it (unsuccesfully) tried to read. */
62 };
63
64 static int bio_new(BIO *bio)
65 {
66 struct bio_bio_st *b;
67
68 b = Malloc(sizeof *b);
69 if (b == NULL)
70 return 0;
71
72 b->peer = NULL;
73 b->size = 17*1024; /* enough for one TLS record (just a default) */
74 b->buf = NULL;
75
76 return 1;
77 }
78
79
80 static int bio_free(BIO *bio)
81 {
82 struct bio_bio_st *b;
83
84 if (bio == NULL)
85 return 0;
86 b = bio->ptr;
87
88 assert(b != NULL);
89
90 if (b->peer)
91 bio_destroy_pair(bio);
92
93 if (b->buf != NULL)
94 {
95 Free(b->buf);
96 }
97
98 Free(b);
99
100 return 1;
101 }
102
103
104
105 static int bio_read(BIO *bio, char *buf, int size)
106 {
107 /* XXX */
108 return -1;
109 }
110
111 static int bio_write(BIO *bio, char *buf, int num)
112 {
113 /* XXX */
114 return -1;
115 }
116
117 static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr)
118 {
119 long ret;
120 struct bio_bio_st *b = bio->ptr;
121
122 assert(b != NULL);
123
124 switch (cmd)
125 {
126 /* XXX Additional commands: */
127 /* - Set buffer size */
128 /* - make pair */
129 /* - destroy pair */
130 /* - get number of bytes that the next write will accept */
131 /* - get number of bytes requested by peer */
132 /* - send "close" */
133
134 case BIO_CTRL_RESET:
135 if (b->buf != NULL)
136 {
137 b->len = 0;
138 b->offset = 0;
139 }
140 ret = 0;
141 break;
142
143 case BIO_CTRL_GET_CLOSE:
144 ret = bio->shutdown;
145 break;
146
147 case BIO_CTRL_SET_CLOSE:
148 bio->shutdown = (int) num;
149 ret = 1;
150 break;
151
152 case BIO_CTRL_PENDING:
153 if (b->peer != NULL)
154 {
155 struct bio_bio_st *peer_b =b->peer->ptr;
156
157 ret = (long) peer_b->len;
158 }
159 else
160 ret = 0;
161 break;
162
163 case BIO_CTRL_WPENDING:
164 if (b->buf != NULL)
165 ret = (long) b->len;
166 else
167 ret = 0;
168 break;
169
170 case BIO_CTRL_DUP:
171 /* XXX */
172 ret = 1;
173 break;
174
175 case BIO_CTRL_FLUSH:
176 ret = 1;
177 break;
178
179 default:
180 ret = 0;
181 }
182 return ret;
183 }
184
185 static int bio_puts(BIO *bio, char *str)
186 {
187 return bio_write(bio, str, strlen(str));
188 }
189
190 /* Until bio_make_pair is used, make a dummy function use it for -pedantic */
191 void dummy() { bio_make_pair(NULL,NULL); }
192
193 static int bio_make_pair(BIO *bio1, BIO *bio2)
194 {
195 struct bio_bio_st *b1, *b2;
196
197 assert(bio1 != NULL);
198 assert(bio2 != NULL);
199
200 b1 = bio1->ptr;
201 b2 = bio2->ptr;
202
203 if (b1->peer != NULL || b2->peer != NULL)
204 {
205 BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE);
206 return 0;
207 }
208
209 if (b1->buf == NULL)
210 {
211 b1->buf = Malloc(b1->size);
212 if (b1->buf == NULL)
213 {
214 BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
215 return 0;
216 }
217 b1->len = 0;
218 b1->offset = 0;
219 }
220
221 if (b2->buf == NULL)
222 {
223 b2->buf = Malloc(b2->size);
224 if (b2->buf == NULL)
225 {
226 BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
227 return 0;
228 }
229 b2->len = 0;
230 b2->offset = 0;
231 }
232
233 b1->peer = bio2;
234 b1->closed = 0;
235 b1->request = 0;
236 b2->peer = bio1;
237 b2->closed = 0;
238 b2->request = 0;
239
240 bio1->init = 1;
241 bio2->init = 1;
242
243 return 1;
244 }
245
246 static void bio_destroy_pair(BIO *bio)
247 {
248 struct bio_bio_st *b = bio->ptr;
249
250 if (b != NULL)
251 {
252 BIO *peer_bio = b->peer;
253
254 if (peer_bio != NULL)
255 {
256 struct bio_bio_st *peer_b = peer_bio->ptr;
257
258 assert(peer_b != NULL);
259 assert(peer_b->peer == bio);
260
261 peer_b->peer = NULL;
262 peer_bio->init = 0;
263 assert(peer_b->buf != NULL);
264 peer_b->len = 0;
265 peer_b->offset = 0;
266
267 b->peer = NULL;
268 bio->init = 0;
269 assert(b->buf != NULL);
270 b->len = 0;
271 b->offset = 0;
272 }
273 }
274 }