]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - crypto/openssl/demos/tunala/buffer.c
Fix multiple OpenSSL vulnerabilities.
[FreeBSD/releng/9.3.git] / crypto / openssl / demos / tunala / buffer.c
1 #include "tunala.h"
2
3 #ifndef NO_BUFFER
4
5 void buffer_init(buffer_t * buf)
6 {
7     buf->used = 0;
8     buf->total_in = buf->total_out = 0;
9 }
10
11 void buffer_close(buffer_t * buf)
12 {
13     /* Our data is static - nothing needs "release", just reset it */
14     buf->used = 0;
15 }
16
17 /* Code these simple ones in compact form */
18 unsigned int buffer_used(buffer_t * buf)
19 {
20     return buf->used;
21 }
22
23 unsigned int buffer_unused(buffer_t * buf)
24 {
25     return (MAX_DATA_SIZE - buf->used);
26 }
27
28 int buffer_full(buffer_t * buf)
29 {
30     return (buf->used == MAX_DATA_SIZE ? 1 : 0);
31 }
32
33 int buffer_notfull(buffer_t * buf)
34 {
35     return (buf->used < MAX_DATA_SIZE ? 1 : 0);
36 }
37
38 int buffer_empty(buffer_t * buf)
39 {
40     return (buf->used == 0 ? 1 : 0);
41 }
42
43 int buffer_notempty(buffer_t * buf)
44 {
45     return (buf->used > 0 ? 1 : 0);
46 }
47
48 unsigned long buffer_total_in(buffer_t * buf)
49 {
50     return buf->total_in;
51 }
52
53 unsigned long buffer_total_out(buffer_t * buf)
54 {
55     return buf->total_out;
56 }
57
58 /*
59  * These 3 static (internal) functions don't adjust the "total" variables as
60  * it's not sure when they're called how it should be interpreted. Only the
61  * higher-level "buffer_[to|from]_[fd|SSL|BIO]" functions should alter these
62  * values.
63  */
64 # if 0                          /* To avoid "unused" warnings */
65 static unsigned int buffer_adddata(buffer_t * buf, const unsigned char *ptr,
66                                    unsigned int size)
67 {
68     unsigned int added = MAX_DATA_SIZE - buf->used;
69     if (added > size)
70         added = size;
71     if (added == 0)
72         return 0;
73     memcpy(buf->data + buf->used, ptr, added);
74     buf->used += added;
75     buf->total_in += added;
76     return added;
77 }
78
79 static unsigned int buffer_tobuffer(buffer_t * to, buffer_t * from, int cap)
80 {
81     unsigned int moved, tomove = from->used;
82     if ((int)tomove > cap)
83         tomove = cap;
84     if (tomove == 0)
85         return 0;
86     moved = buffer_adddata(to, from->data, tomove);
87     if (moved == 0)
88         return 0;
89     buffer_takedata(from, NULL, moved);
90     return moved;
91 }
92 # endif
93
94 static unsigned int buffer_takedata(buffer_t * buf, unsigned char *ptr,
95                                     unsigned int size)
96 {
97     unsigned int taken = buf->used;
98     if (taken > size)
99         taken = size;
100     if (taken == 0)
101         return 0;
102     if (ptr)
103         memcpy(ptr, buf->data, taken);
104     buf->used -= taken;
105     /* Do we have to scroll? */
106     if (buf->used > 0)
107         memmove(buf->data, buf->data + taken, buf->used);
108     return taken;
109 }
110
111 # ifndef NO_IP
112
113 int buffer_from_fd(buffer_t * buf, int fd)
114 {
115     int toread = buffer_unused(buf);
116     if (toread == 0)
117         /* Shouldn't be called in this case! */
118         abort();
119     toread = read(fd, buf->data + buf->used, toread);
120     if (toread > 0) {
121         buf->used += toread;
122         buf->total_in += toread;
123     }
124     return toread;
125 }
126
127 int buffer_to_fd(buffer_t * buf, int fd)
128 {
129     int towrite = buffer_used(buf);
130     if (towrite == 0)
131         /* Shouldn't be called in this case! */
132         abort();
133     towrite = write(fd, buf->data, towrite);
134     if (towrite > 0) {
135         buffer_takedata(buf, NULL, towrite);
136         buf->total_out += towrite;
137     }
138     return towrite;
139 }
140
141 # endif                         /* !defined(NO_IP) */
142
143 # ifndef NO_OPENSSL
144
145 static void int_ssl_check(SSL *s, int ret)
146 {
147     int e = SSL_get_error(s, ret);
148     switch (e) {
149         /*
150          * These seem to be harmless and already "dealt with" by our
151          * non-blocking environment. NB: "ZERO_RETURN" is the clean "error"
152          * indicating a successfully closed SSL tunnel. We let this happen
153          * because our IO loop should not appear to have broken on this
154          * condition - and outside the IO loop, the "shutdown" state is
155          * checked.
156          */
157     case SSL_ERROR_NONE:
158     case SSL_ERROR_WANT_READ:
159     case SSL_ERROR_WANT_WRITE:
160     case SSL_ERROR_WANT_X509_LOOKUP:
161     case SSL_ERROR_ZERO_RETURN:
162         return;
163         /*
164          * These seem to be indications of a genuine error that should result
165          * in the SSL tunnel being regarded as "dead".
166          */
167     case SSL_ERROR_SYSCALL:
168     case SSL_ERROR_SSL:
169         SSL_set_app_data(s, (char *)1);
170         return;
171     default:
172         break;
173     }
174     /*
175      * For any other errors that (a) exist, and (b) crop up - we need to
176      * interpret what to do with them - so "politely inform" the caller that
177      * the code needs updating here.
178      */
179     abort();
180 }
181
182 void buffer_from_SSL(buffer_t * buf, SSL *ssl)
183 {
184     int ret;
185     if (!ssl || buffer_full(buf))
186         return;
187     ret = SSL_read(ssl, buf->data + buf->used, buffer_unused(buf));
188     if (ret > 0) {
189         buf->used += ret;
190         buf->total_in += ret;
191     }
192     if (ret < 0)
193         int_ssl_check(ssl, ret);
194 }
195
196 void buffer_to_SSL(buffer_t * buf, SSL *ssl)
197 {
198     int ret;
199     if (!ssl || buffer_empty(buf))
200         return;
201     ret = SSL_write(ssl, buf->data, buf->used);
202     if (ret > 0) {
203         buffer_takedata(buf, NULL, ret);
204         buf->total_out += ret;
205     }
206     if (ret < 0)
207         int_ssl_check(ssl, ret);
208 }
209
210 void buffer_from_BIO(buffer_t * buf, BIO *bio)
211 {
212     int ret;
213     if (!bio || buffer_full(buf))
214         return;
215     ret = BIO_read(bio, buf->data + buf->used, buffer_unused(buf));
216     if (ret > 0) {
217         buf->used += ret;
218         buf->total_in += ret;
219     }
220 }
221
222 void buffer_to_BIO(buffer_t * buf, BIO *bio)
223 {
224     int ret;
225     if (!bio || buffer_empty(buf))
226         return;
227     ret = BIO_write(bio, buf->data, buf->used);
228     if (ret > 0) {
229         buffer_takedata(buf, NULL, ret);
230         buf->total_out += ret;
231     }
232 }
233
234 # endif                         /* !defined(NO_OPENSSL) */
235
236 #endif                          /* !defined(NO_BUFFER) */