]> git.saurik.com Git - apple/security.git/blob - Security/libsecurity_apple_csp/open_ssl/bio/bio_lib.c
Security-57031.40.6.tar.gz
[apple/security.git] / Security / libsecurity_apple_csp / open_ssl / bio / bio_lib.c
1 /*
2 * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /* crypto/bio/bio_lib.c */
20 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
21 * All rights reserved.
22 *
23 * This package is an SSL implementation written
24 * by Eric Young (eay@cryptsoft.com).
25 * The implementation was written so as to conform with Netscapes SSL.
26 *
27 * This library is free for commercial and non-commercial use as long as
28 * the following conditions are aheared to. The following conditions
29 * apply to all code found in this distribution, be it the RC4, RSA,
30 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
31 * included with this distribution is covered by the same copyright terms
32 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
33 *
34 * Copyright remains Eric Young's, and as such any Copyright notices in
35 * the code are not to be removed.
36 * If this package is used in a product, Eric Young should be given attribution
37 * as the author of the parts of the library used.
38 * This can be in the form of a textual message at program startup or
39 * in documentation (online or textual) provided with the package.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. All advertising materials mentioning features or use of this software
50 * must display the following acknowledgement:
51 * "This product includes cryptographic software written by
52 * Eric Young (eay@cryptsoft.com)"
53 * The word 'cryptographic' can be left out if the rouines from the library
54 * being used are not cryptographic related :-).
55 * 4. If you include any Windows specific code (or a derivative thereof) from
56 * the apps directory (application code) you must include an acknowledgement:
57 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
58 *
59 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * The licence and distribution terms for any publically available version or
72 * derivative of this code cannot be changed. i.e. this code cannot simply be
73 * copied and put under another distribution licence
74 * [including the GNU Public Licence.]
75 */
76
77 #include <stdio.h>
78 #include <errno.h>
79 #include <openssl/crypto.h>
80 #include "cryptlib.h"
81 #include <openssl/bio.h>
82 #include <openssl/stack.h>
83
84 static STACK_OF(CRYPTO_EX_DATA_FUNCS) *bio_meth=NULL;
85 static int bio_meth_num=0;
86
87 BIO *BIO_new(const BIO_METHOD *method)
88 {
89 BIO *ret=NULL;
90
91 ret=(BIO *)Malloc(sizeof(BIO));
92 if (ret == NULL)
93 {
94 BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
95 return(NULL);
96 }
97 if (!BIO_set(ret,method))
98 {
99 Free(ret);
100 ret=NULL;
101 }
102 return(ret);
103 }
104
105 int BIO_set(BIO *bio, const BIO_METHOD *method)
106 {
107 bio->method=method;
108 bio->callback=NULL;
109 bio->cb_arg=NULL;
110 bio->init=0;
111 bio->shutdown=1;
112 bio->flags=0;
113 bio->retry_reason=0;
114 bio->num=0;
115 bio->ptr=NULL;
116 bio->prev_bio=NULL;
117 bio->next_bio=NULL;
118 bio->references=1;
119 bio->num_read=0L;
120 bio->num_write=0L;
121 CRYPTO_new_ex_data(bio_meth,bio,&bio->ex_data);
122 if (method->create != NULL)
123 if (!method->create(bio))
124 return(0);
125 return(1);
126 }
127
128 int BIO_free(BIO *a)
129 {
130 int ret=0,i;
131
132 if (a == NULL) return(0);
133
134 i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO);
135 #ifdef REF_PRINT
136 REF_PRINT("BIO",a);
137 #endif
138 if (i > 0) return(1);
139 #ifdef REF_CHECK
140 if (i < 0)
141 {
142 fprintf(stderr,"BIO_free, bad reference count\n");
143 abort();
144 }
145 #endif
146 if ((a->callback != NULL) &&
147 ((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
148 return(i);
149
150 CRYPTO_free_ex_data(bio_meth,a,&a->ex_data);
151
152 if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
153 ret=a->method->destroy(a);
154 Free(a);
155 return(1);
156 }
157
158 int BIO_read(BIO *b, void *out, int outl)
159 {
160 int i;
161 long (*cb)();
162
163 if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
164 {
165 BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
166 return(-2);
167 }
168
169 cb=b->callback;
170 if ((cb != NULL) &&
171 ((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
172 return(i);
173
174 if (!b->init)
175 {
176 BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED);
177 return(-2);
178 }
179
180 i=b->method->bread(b,out,outl);
181
182 if (i > 0) b->num_read+=(unsigned long)i;
183
184 if (cb != NULL)
185 i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
186 0L,(long)i);
187 return(i);
188 }
189
190 int BIO_write(BIO *b, const void *in, int inl)
191 {
192 int i;
193 long (*cb)();
194
195 if (b == NULL)
196 return(0);
197
198 cb=b->callback;
199 if ((b->method == NULL) || (b->method->bwrite == NULL))
200 {
201 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
202 return(-2);
203 }
204
205 if ((cb != NULL) &&
206 ((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
207 return(i);
208
209 if (!b->init)
210 {
211 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED);
212 return(-2);
213 }
214
215 i=b->method->bwrite(b,in,inl);
216
217 if (i > 0) b->num_write+=(unsigned long)i;
218
219 /* This is evil and not thread safe. If the BIO has been freed,
220 * we must not call the callback. The only way to be able to
221 * determine this is the reference count which is now invalid since
222 * the memory has been free()ed.
223 */
224 if (b->references <= 0) abort();
225 if (cb != NULL) /* && (b->references >= 1)) */
226 i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
227 0L,(long)i);
228 return(i);
229 }
230
231 int BIO_puts(BIO *b, const char *in)
232 {
233 int i;
234 long (*cb)();
235
236 if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
237 {
238 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
239 return(-2);
240 }
241
242 cb=b->callback;
243
244 if ((cb != NULL) &&
245 ((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
246 return(i);
247
248 if (!b->init)
249 {
250 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);
251 return(-2);
252 }
253
254 i=b->method->bputs(b,in);
255
256 if (cb != NULL)
257 i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
258 0L,(long)i);
259 return(i);
260 }
261
262 int BIO_gets(BIO *b, char *in, int inl)
263 {
264 int i;
265 long (*cb)();
266
267 if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
268 {
269 BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
270 return(-2);
271 }
272
273 cb=b->callback;
274
275 if ((cb != NULL) &&
276 ((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
277 return(i);
278
279 if (!b->init)
280 {
281 BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);
282 return(-2);
283 }
284
285 i=b->method->bgets(b,in,inl);
286
287 if (cb != NULL)
288 i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
289 0L,(long)i);
290 return(i);
291 }
292
293 long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
294 {
295 int i;
296
297 i=iarg;
298 return(BIO_ctrl(b,cmd,larg,(char *)&i));
299 }
300
301 char *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
302 {
303 char *p=NULL;
304
305 if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
306 return(NULL);
307 else
308 return(p);
309 }
310
311 long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
312 {
313 long ret;
314 long (*cb)();
315
316 if (b == NULL) return(0);
317
318 if ((b->method == NULL) || (b->method->ctrl == NULL))
319 {
320 BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
321 return(-2);
322 }
323
324 cb=b->callback;
325
326 if ((cb != NULL) &&
327 ((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
328 return(ret);
329
330 ret=b->method->ctrl(b,cmd,larg,parg);
331
332 if (cb != NULL)
333 ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
334 larg,ret);
335 return(ret);
336 }
337
338 long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)())
339 {
340 long ret;
341 long (*cb)();
342
343 if (b == NULL) return(0);
344
345 if ((b->method == NULL) || (b->method->callback_ctrl == NULL))
346 {
347 BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
348 return(-2);
349 }
350
351 cb=b->callback;
352
353 if ((cb != NULL) &&
354 ((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0))
355 return(ret);
356
357 ret=b->method->callback_ctrl(b,cmd,fp);
358
359 if (cb != NULL)
360 ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd,
361 0,ret);
362 return(ret);
363 }
364
365 /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
366 * do; but those macros have inappropriate return type, and for interfacing
367 * from other programming languages, C macros aren't much of a help anyway. */
368 size_t BIO_ctrl_pending(BIO *bio)
369 {
370 return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
371 }
372
373 size_t BIO_ctrl_wpending(BIO *bio)
374 {
375 return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
376 }
377
378
379 /* put the 'bio' on the end of b's list of operators */
380 BIO *BIO_push(BIO *b, BIO *bio)
381 {
382 BIO *lb;
383
384 if (b == NULL) return(bio);
385 lb=b;
386 while (lb->next_bio != NULL)
387 lb=lb->next_bio;
388 lb->next_bio=bio;
389 if (bio != NULL)
390 bio->prev_bio=lb;
391 /* called to do internal processing */
392 BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
393 return(b);
394 }
395
396 /* Remove the first and return the rest */
397 BIO *BIO_pop(BIO *b)
398 {
399 BIO *ret;
400
401 if (b == NULL) return(NULL);
402 ret=b->next_bio;
403
404 if (b->prev_bio != NULL)
405 b->prev_bio->next_bio=b->next_bio;
406 if (b->next_bio != NULL)
407 b->next_bio->prev_bio=b->prev_bio;
408
409 b->next_bio=NULL;
410 b->prev_bio=NULL;
411 BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
412 return(ret);
413 }
414
415 BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
416 {
417 BIO *b,*last;
418
419 b=last=bio;
420 for (;;)
421 {
422 if (!BIO_should_retry(b)) break;
423 last=b;
424 b=b->next_bio;
425 if (b == NULL) break;
426 }
427 if (reason != NULL) *reason=last->retry_reason;
428 return(last);
429 }
430
431 int BIO_get_retry_reason(BIO *bio)
432 {
433 return(bio->retry_reason);
434 }
435
436 BIO *BIO_find_type(BIO *bio, int type)
437 {
438 int mt,mask;
439
440 mask=type&0xff;
441 do {
442 if (bio->method != NULL)
443 {
444 mt=bio->method->type;
445
446 if (!mask)
447 {
448 if (mt & type) return(bio);
449 }
450 else if (mt == type)
451 return(bio);
452 }
453 bio=bio->next_bio;
454 } while (bio != NULL);
455 return(NULL);
456 }
457
458 void BIO_free_all(BIO *bio)
459 {
460 BIO *b;
461 int ref;
462
463 while (bio != NULL)
464 {
465 b=bio;
466 ref=b->references;
467 bio=bio->next_bio;
468 BIO_free(b);
469 /* Since ref count > 1, don't free anyone else. */
470 if (ref > 1) break;
471 }
472 }
473
474 BIO *BIO_dup_chain(BIO *in)
475 {
476 BIO *ret=NULL,*eoc=NULL,*bio,*new;
477
478 for (bio=in; bio != NULL; bio=bio->next_bio)
479 {
480 if ((new=BIO_new(bio->method)) == NULL) goto err;
481 new->callback=bio->callback;
482 new->cb_arg=bio->cb_arg;
483 new->init=bio->init;
484 new->shutdown=bio->shutdown;
485 new->flags=bio->flags;
486
487 /* This will let SSL_s_sock() work with stdin/stdout */
488 new->num=bio->num;
489
490 if (!BIO_dup_state(bio,(char *)new))
491 {
492 BIO_free(new);
493 goto err;
494 }
495
496 /* copy app data */
497 if (!CRYPTO_dup_ex_data(bio_meth,&new->ex_data,&bio->ex_data))
498 goto err;
499
500 if (ret == NULL)
501 {
502 eoc=new;
503 ret=eoc;
504 }
505 else
506 {
507 BIO_push(eoc,new);
508 eoc=new;
509 }
510 }
511 return(ret);
512 err:
513 if (ret != NULL)
514 BIO_free(ret);
515 return(NULL);
516 }
517
518 void BIO_copy_next_retry(BIO *b)
519 {
520 BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
521 b->retry_reason=b->next_bio->retry_reason;
522 }
523
524 int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
525 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
526 {
527 bio_meth_num++;
528 return(CRYPTO_get_ex_new_index(bio_meth_num-1,&bio_meth,
529 argl,argp,new_func,dup_func,free_func));
530 }
531
532 int BIO_set_ex_data(BIO *bio, int idx, void *data)
533 {
534 return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
535 }
536
537 void *BIO_get_ex_data(BIO *bio, int idx)
538 {
539 return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
540 }
541
542 unsigned long BIO_number_read(BIO *bio)
543 {
544 if(bio) return bio->num_read;
545 return 0;
546 }
547
548 unsigned long BIO_number_written(BIO *bio)
549 {
550 if(bio) return bio->num_write;
551 return 0;
552 }