bss_fd.c revision 290207
123693Speter/* crypto/bio/bss_fd.c */ 21590Srgrimes/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 31590Srgrimes * All rights reserved. 41590Srgrimes * 51590Srgrimes * This package is an SSL implementation written 61590Srgrimes * by Eric Young (eay@cryptsoft.com). 71590Srgrimes * The implementation was written so as to conform with Netscapes SSL. 81590Srgrimes * 91590Srgrimes * This library is free for commercial and non-commercial use as long as 101590Srgrimes * the following conditions are aheared to. The following conditions 111590Srgrimes * apply to all code found in this distribution, be it the RC4, RSA, 121590Srgrimes * lhash, DES, etc., code; not just the SSL code. The SSL documentation 131590Srgrimes * included with this distribution is covered by the same copyright terms 141590Srgrimes * except that the holder is Tim Hudson (tjh@cryptsoft.com). 151590Srgrimes * 161590Srgrimes * Copyright remains Eric Young's, and as such any Copyright notices in 171590Srgrimes * the code are not to be removed. 181590Srgrimes * If this package is used in a product, Eric Young should be given attribution 191590Srgrimes * as the author of the parts of the library used. 201590Srgrimes * This can be in the form of a textual message at program startup or 211590Srgrimes * in documentation (online or textual) provided with the package. 221590Srgrimes * 231590Srgrimes * Redistribution and use in source and binary forms, with or without 241590Srgrimes * modification, are permitted provided that the following conditions 251590Srgrimes * are met: 261590Srgrimes * 1. Redistributions of source code must retain the copyright 271590Srgrimes * notice, this list of conditions and the following disclaimer. 2823693Speter * 2. Redistributions in binary form must reproduce the above copyright 2950477Speter * notice, this list of conditions and the following disclaimer in the 301590Srgrimes * documentation and/or other materials provided with the distribution. 31240506Seadler * 3. All advertising materials mentioning features or use of this software 321590Srgrimes * must display the following acknowledgement: 3379535Sru * "This product includes cryptographic software written by 341590Srgrimes * Eric Young (eay@cryptsoft.com)" 351590Srgrimes * The word 'cryptographic' can be left out if the rouines from the library 361590Srgrimes * being used are not cryptographic related :-). 371590Srgrimes * 4. If you include any Windows specific code (or a derivative thereof) from 3868963Sru * the apps directory (application code) you must include an acknowledgement: 39168632Sdes * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4070197Sru * 4170197Sru * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 421590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 431590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4468963Sru * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4595083Scharnier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 461590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 471590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48107262Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49100521Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50100521Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51100521Sume * SUCH DAMAGE. 52100521Sume * 53100521Sume * The licence and distribution terms for any publically available version or 54100521Sume * derivative of this code cannot be changed. i.e. this code cannot simply be 55100521Sume * copied and put under another distribution licence 56100521Sume * [including the GNU Public Licence.] 571590Srgrimes */ 5895083Scharnier 591590Srgrimes#include <stdio.h> 602537Spst#include <errno.h> 6157670Ssheldonh#define USE_SOCKETS 6257670Ssheldonh#include "cryptlib.h" 632537Spst 642537Spst#if defined(OPENSSL_NO_POSIX_IO) 6567483Sru/* 6667483Sru * Dummy placeholder for BIO_s_fd... 6767483Sru */ 6867483SruBIO *BIO_new_fd(int fd, int close_flag) 691590Srgrimes{ 701590Srgrimes return NULL; 711590Srgrimes} 7269909Sru 7369909Sruint BIO_fd_non_fatal_error(int err) 7469909Sru{ 7572109Scharnier return 0; 762537Spst} 772537Spst 781590Srgrimesint BIO_fd_should_retry(int i) 791590Srgrimes{ 801590Srgrimes return 0; 812537Spst} 822537Spst 832537SpstBIO_METHOD *BIO_s_fd(void) 842537Spst{ 852537Spst return NULL; 862537Spst} 872537Spst#else 882537Spst/* 892537Spst * As for unconditional usage of "UPLINK" interface in this module. 902537Spst * Trouble is that unlike Unix file descriptors [which are indexes 9199249Smini * in kernel-side per-process table], corresponding descriptors on 9299249Smini * platforms which require "UPLINK" interface seem to be indexes 93131491Sru * in a user-land, non-global table. Well, in fact they are indexes 94131491Sru * in stdio _iob[], and recall that _iob[] was the very reason why 9599249Smini * "UPLINK" interface was introduced in first place. But one way on 9699249Smini * another. Neither libcrypto or libssl use this BIO meaning that 9799249Smini * file descriptors can only be provided by application. Therefore 98117010Sjmallett * "UPLINK" calls are due... 99202756Sed */ 1001590Srgrimes# include "bio_lcl.h" 10195083Scharnier 1021590Srgrimesstatic int fd_write(BIO *h, const char *buf, int num); 1031590Srgrimesstatic int fd_read(BIO *h, char *buf, int size); 1041590Srgrimesstatic int fd_puts(BIO *h, const char *str); 1052537Spststatic int fd_gets(BIO *h, char *buf, int size); 106107262Srustatic long fd_ctrl(BIO *h, int cmd, long arg1, void *arg2); 107107262Srustatic int fd_new(BIO *h); 108107262Srustatic int fd_free(BIO *data); 1091590Srgrimesint BIO_fd_should_retry(int s); 110107262Sru 1111590Srgrimesstatic BIO_METHOD methods_fdp = { 1121590Srgrimes BIO_TYPE_FD, "file descriptor", 1131590Srgrimes fd_write, 1141590Srgrimes fd_read, 1151590Srgrimes fd_puts, 1161590Srgrimes fd_gets, 1171590Srgrimes fd_ctrl, 1181590Srgrimes fd_new, 1191590Srgrimes fd_free, 1201590Srgrimes NULL, 1212537Spst}; 1221590Srgrimes 1231590SrgrimesBIO_METHOD *BIO_s_fd(void) 1241590Srgrimes{ 1251590Srgrimes return (&methods_fdp); 1261590Srgrimes} 1271590Srgrimes 1281590SrgrimesBIO *BIO_new_fd(int fd, int close_flag) 1291590Srgrimes{ 1302537Spst BIO *ret; 1312537Spst ret = BIO_new(BIO_s_fd()); 1322537Spst if (ret == NULL) 1332537Spst return (NULL); 1341590Srgrimes BIO_set_fd(ret, fd, close_flag); 13595083Scharnier return (ret); 1361590Srgrimes} 1371590Srgrimes 1381590Srgrimesstatic int fd_new(BIO *bi) 13968963Sru{ 1401590Srgrimes bi->init = 0; 141107262Sru bi->num = -1; 142107262Sru bi->ptr = NULL; 143107262Sru bi->flags = BIO_FLAGS_UPLINK; /* essentially redundant */ 1441590Srgrimes return (1); 145107262Sru} 1461590Srgrimes 1471590Srgrimesstatic int fd_free(BIO *a) 1481590Srgrimes{ 1491590Srgrimes if (a == NULL) 1501590Srgrimes return (0); 1511590Srgrimes if (a->shutdown) { 1521590Srgrimes if (a->init) { 1531590Srgrimes UP_close(a->num); 1541590Srgrimes } 1551590Srgrimes a->init = 0; 1561590Srgrimes a->flags = BIO_FLAGS_UPLINK; 15768963Sru } 1581590Srgrimes return (1); 1591590Srgrimes} 1601590Srgrimes 1611590Srgrimesstatic int fd_read(BIO *b, char *out, int outl) 16268963Sru{ 1631590Srgrimes int ret = 0; 1641590Srgrimes 1651590Srgrimes if (out != NULL) { 1661590Srgrimes clear_sys_error(); 1671590Srgrimes ret = UP_read(b->num, out, outl); 1681590Srgrimes BIO_clear_retry_flags(b); 1691590Srgrimes if (ret <= 0) { 1701590Srgrimes if (BIO_fd_should_retry(ret)) 1711590Srgrimes BIO_set_retry_read(b); 17268963Sru } 1731590Srgrimes } 1741590Srgrimes return (ret); 17595083Scharnier} 17695083Scharnier 17795083Scharnierstatic int fd_write(BIO *b, const char *in, int inl) 1781590Srgrimes{ 1791590Srgrimes int ret; 1801590Srgrimes clear_sys_error(); 1811590Srgrimes ret = UP_write(b->num, in, inl); 1821590Srgrimes BIO_clear_retry_flags(b); 1831590Srgrimes if (ret <= 0) { 1841590Srgrimes if (BIO_fd_should_retry(ret)) 1851590Srgrimes BIO_set_retry_write(b); 1861590Srgrimes } 1871590Srgrimes return (ret); 1881590Srgrimes} 1891590Srgrimes 1901590Srgrimesstatic long fd_ctrl(BIO *b, int cmd, long num, void *ptr) 1911590Srgrimes{ 1921590Srgrimes long ret = 1; 1935369Sjkh int *ip; 1945369Sjkh 195107262Sru switch (cmd) { 1965369Sjkh case BIO_CTRL_RESET: 197150316Sdds num = 0; 19868963Sru case BIO_C_FILE_SEEK: 1995369Sjkh ret = (long)UP_lseek(b->num, num, 0); 20064775Sbrian break; 20164775Sbrian case BIO_C_FILE_TELL: 20264775Sbrian case BIO_CTRL_INFO: 20364775Sbrian ret = (long)UP_lseek(b->num, 0, 1); 20464775Sbrian break; 205108257Sru case BIO_C_SET_FD: 20664775Sbrian fd_free(b); 20765069Ssheldonh b->num = *((int *)ptr); 20865064Sbrian b->shutdown = (int)num; 2092589Spst b->init = 1; 21095083Scharnier break; 21195083Scharnier case BIO_C_GET_FD: 21295083Scharnier if (b->init) { 2132589Spst ip = (int *)ptr; 2142589Spst if (ip != NULL) 2152589Spst *ip = b->num; 21668963Sru ret = b->num; 2172589Spst } else 21823693Speter ret = -1; 219202756Sed break; 22064775Sbrian case BIO_CTRL_GET_CLOSE: 22164775Sbrian ret = b->shutdown; 222202756Sed break; 22323693Speter case BIO_CTRL_SET_CLOSE: 22423693Speter b->shutdown = (int)num; 2251590Srgrimes break; 2261590Srgrimes case BIO_CTRL_PENDING: 2271590Srgrimes case BIO_CTRL_WPENDING: 2281590Srgrimes ret = 0; 22964775Sbrian break; 23079366Sru case BIO_CTRL_DUP: 23127836Swollman case BIO_CTRL_FLUSH: 23227836Swollman ret = 1; 23327836Swollman break; 23427836Swollman default: 23527836Swollman ret = 0; 23627836Swollman break; 2371590Srgrimes } 2381590Srgrimes return (ret); 23968963Sru} 2401590Srgrimes 2411590Srgrimesstatic int fd_puts(BIO *bp, const char *str) 242168657Sru{ 243132277Stjr int n, ret; 244132277Stjr 245132277Stjr n = strlen(str); 246 ret = fd_write(bp, str, n); 247 return (ret); 248} 249 250static int fd_gets(BIO *bp, char *buf, int size) 251{ 252 int ret = 0; 253 char *ptr = buf; 254 char *end = buf + size - 1; 255 256 while ((ptr < end) && (fd_read(bp, ptr, 1) > 0) && (ptr[0] != '\n')) 257 ptr++; 258 259 ptr[0] = '\0'; 260 261 if (buf[0] != '\0') 262 ret = strlen(buf); 263 return (ret); 264} 265 266int BIO_fd_should_retry(int i) 267{ 268 int err; 269 270 if ((i == 0) || (i == -1)) { 271 err = get_last_sys_error(); 272 273# if defined(OPENSSL_SYS_WINDOWS) && 0/* more microsoft stupidity? perhaps 274 * not? Ben 4/1/99 */ 275 if ((i == -1) && (err == 0)) 276 return (1); 277# endif 278 279 return (BIO_fd_non_fatal_error(err)); 280 } 281 return (0); 282} 283 284int BIO_fd_non_fatal_error(int err) 285{ 286 switch (err) { 287 288# ifdef EWOULDBLOCK 289# ifdef WSAEWOULDBLOCK 290# if WSAEWOULDBLOCK != EWOULDBLOCK 291 case EWOULDBLOCK: 292# endif 293# else 294 case EWOULDBLOCK: 295# endif 296# endif 297 298# if defined(ENOTCONN) 299 case ENOTCONN: 300# endif 301 302# ifdef EINTR 303 case EINTR: 304# endif 305 306# ifdef EAGAIN 307# if EWOULDBLOCK != EAGAIN 308 case EAGAIN: 309# endif 310# endif 311 312# ifdef EPROTO 313 case EPROTO: 314# endif 315 316# ifdef EINPROGRESS 317 case EINPROGRESS: 318# endif 319 320# ifdef EALREADY 321 case EALREADY: 322# endif 323 return (1); 324 /* break; */ 325 default: 326 break; 327 } 328 return (0); 329} 330#endif 331