xref: /freebsd/crypto/openssl/crypto/bio/bss_fd.c (revision b077aed3)
1e71b7053SJung-uk Kim /*
2b077aed3SPierre Pronchery  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
374664626SKris Kennaway  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5e71b7053SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim  * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim  * https://www.openssl.org/source/license.html
874664626SKris Kennaway  */
974664626SKris Kennaway 
105c87c606SMark Murray #include <stdio.h>
115c87c606SMark Murray #include <errno.h>
12e71b7053SJung-uk Kim 
1317f01e99SJung-uk Kim #include "bio_local.h"
141f13597dSJung-uk Kim 
151f13597dSJung-uk Kim #if defined(OPENSSL_NO_POSIX_IO)
161f13597dSJung-uk Kim /*
177bded2dbSJung-uk Kim  * Dummy placeholder for BIO_s_fd...
181f13597dSJung-uk Kim  */
BIO_new_fd(int fd,int close_flag)197bded2dbSJung-uk Kim BIO *BIO_new_fd(int fd, int close_flag)
207bded2dbSJung-uk Kim {
217bded2dbSJung-uk Kim     return NULL;
227bded2dbSJung-uk Kim }
237bded2dbSJung-uk Kim 
BIO_fd_non_fatal_error(int err)247bded2dbSJung-uk Kim int BIO_fd_non_fatal_error(int err)
257bded2dbSJung-uk Kim {
267bded2dbSJung-uk Kim     return 0;
277bded2dbSJung-uk Kim }
287bded2dbSJung-uk Kim 
BIO_fd_should_retry(int i)297bded2dbSJung-uk Kim int BIO_fd_should_retry(int i)
307bded2dbSJung-uk Kim {
317bded2dbSJung-uk Kim     return 0;
327bded2dbSJung-uk Kim }
337bded2dbSJung-uk Kim 
BIO_s_fd(void)34e71b7053SJung-uk Kim const BIO_METHOD *BIO_s_fd(void)
357bded2dbSJung-uk Kim {
367bded2dbSJung-uk Kim     return NULL;
377bded2dbSJung-uk Kim }
381f13597dSJung-uk Kim #else
393b4e3dcbSSimon L. B. Nielsen /*
403b4e3dcbSSimon L. B. Nielsen  * As for unconditional usage of "UPLINK" interface in this module.
413b4e3dcbSSimon L. B. Nielsen  * Trouble is that unlike Unix file descriptors [which are indexes
423b4e3dcbSSimon L. B. Nielsen  * in kernel-side per-process table], corresponding descriptors on
433b4e3dcbSSimon L. B. Nielsen  * platforms which require "UPLINK" interface seem to be indexes
443b4e3dcbSSimon L. B. Nielsen  * in a user-land, non-global table. Well, in fact they are indexes
453b4e3dcbSSimon L. B. Nielsen  * in stdio _iob[], and recall that _iob[] was the very reason why
463b4e3dcbSSimon L. B. Nielsen  * "UPLINK" interface was introduced in first place. But one way on
473b4e3dcbSSimon L. B. Nielsen  * another. Neither libcrypto or libssl use this BIO meaning that
483b4e3dcbSSimon L. B. Nielsen  * file descriptors can only be provided by application. Therefore
493b4e3dcbSSimon L. B. Nielsen  * "UPLINK" calls are due...
503b4e3dcbSSimon L. B. Nielsen  */
515c87c606SMark Murray static int fd_write(BIO *h, const char *buf, int num);
525c87c606SMark Murray static int fd_read(BIO *h, char *buf, int size);
535c87c606SMark Murray static int fd_puts(BIO *h, const char *str);
541f13597dSJung-uk Kim static int fd_gets(BIO *h, char *buf, int size);
555c87c606SMark Murray static long fd_ctrl(BIO *h, int cmd, long arg1, void *arg2);
565c87c606SMark Murray static int fd_new(BIO *h);
575c87c606SMark Murray static int fd_free(BIO *data);
585c87c606SMark Murray int BIO_fd_should_retry(int s);
595c87c606SMark Murray 
60e71b7053SJung-uk Kim static const BIO_METHOD methods_fdp = {
61e71b7053SJung-uk Kim     BIO_TYPE_FD,
62e71b7053SJung-uk Kim     "file descriptor",
63e71b7053SJung-uk Kim     bwrite_conv,
645c87c606SMark Murray     fd_write,
65e71b7053SJung-uk Kim     bread_conv,
665c87c606SMark Murray     fd_read,
675c87c606SMark Murray     fd_puts,
681f13597dSJung-uk Kim     fd_gets,
695c87c606SMark Murray     fd_ctrl,
705c87c606SMark Murray     fd_new,
715c87c606SMark Murray     fd_free,
72e71b7053SJung-uk Kim     NULL,                       /* fd_callback_ctrl */
735c87c606SMark Murray };
745c87c606SMark Murray 
BIO_s_fd(void)75e71b7053SJung-uk Kim const BIO_METHOD *BIO_s_fd(void)
765c87c606SMark Murray {
77e71b7053SJung-uk Kim     return &methods_fdp;
785c87c606SMark Murray }
795c87c606SMark Murray 
BIO_new_fd(int fd,int close_flag)805c87c606SMark Murray BIO *BIO_new_fd(int fd, int close_flag)
815c87c606SMark Murray {
825c87c606SMark Murray     BIO *ret;
835c87c606SMark Murray     ret = BIO_new(BIO_s_fd());
846f9291ceSJung-uk Kim     if (ret == NULL)
85e71b7053SJung-uk Kim         return NULL;
865c87c606SMark Murray     BIO_set_fd(ret, fd, close_flag);
87e71b7053SJung-uk Kim     return ret;
885c87c606SMark Murray }
895c87c606SMark Murray 
fd_new(BIO * bi)905c87c606SMark Murray static int fd_new(BIO *bi)
915c87c606SMark Murray {
925c87c606SMark Murray     bi->init = 0;
933b4e3dcbSSimon L. B. Nielsen     bi->num = -1;
945c87c606SMark Murray     bi->ptr = NULL;
95b077aed3SPierre Pronchery     bi->flags = BIO_FLAGS_UPLINK_INTERNAL; /* essentially redundant */
96e71b7053SJung-uk Kim     return 1;
975c87c606SMark Murray }
985c87c606SMark Murray 
fd_free(BIO * a)995c87c606SMark Murray static int fd_free(BIO *a)
1005c87c606SMark Murray {
1016f9291ceSJung-uk Kim     if (a == NULL)
102e71b7053SJung-uk Kim         return 0;
1036f9291ceSJung-uk Kim     if (a->shutdown) {
1046f9291ceSJung-uk Kim         if (a->init) {
1053b4e3dcbSSimon L. B. Nielsen             UP_close(a->num);
1065c87c606SMark Murray         }
1075c87c606SMark Murray         a->init = 0;
108b077aed3SPierre Pronchery         a->flags = BIO_FLAGS_UPLINK_INTERNAL;
1095c87c606SMark Murray     }
110e71b7053SJung-uk Kim     return 1;
1115c87c606SMark Murray }
1125c87c606SMark Murray 
fd_read(BIO * b,char * out,int outl)1135c87c606SMark Murray static int fd_read(BIO *b, char *out, int outl)
1145c87c606SMark Murray {
1155c87c606SMark Murray     int ret = 0;
1165c87c606SMark Murray 
1176f9291ceSJung-uk Kim     if (out != NULL) {
1185c87c606SMark Murray         clear_sys_error();
1193b4e3dcbSSimon L. B. Nielsen         ret = UP_read(b->num, out, outl);
1205c87c606SMark Murray         BIO_clear_retry_flags(b);
1216f9291ceSJung-uk Kim         if (ret <= 0) {
1225c87c606SMark Murray             if (BIO_fd_should_retry(ret))
1235c87c606SMark Murray                 BIO_set_retry_read(b);
12417f01e99SJung-uk Kim             else if (ret == 0)
12517f01e99SJung-uk Kim                 b->flags |= BIO_FLAGS_IN_EOF;
1265c87c606SMark Murray         }
1275c87c606SMark Murray     }
128e71b7053SJung-uk Kim     return ret;
1295c87c606SMark Murray }
1305c87c606SMark Murray 
fd_write(BIO * b,const char * in,int inl)1315c87c606SMark Murray static int fd_write(BIO *b, const char *in, int inl)
1325c87c606SMark Murray {
1335c87c606SMark Murray     int ret;
1345c87c606SMark Murray     clear_sys_error();
1353b4e3dcbSSimon L. B. Nielsen     ret = UP_write(b->num, in, inl);
1365c87c606SMark Murray     BIO_clear_retry_flags(b);
1376f9291ceSJung-uk Kim     if (ret <= 0) {
1385c87c606SMark Murray         if (BIO_fd_should_retry(ret))
1395c87c606SMark Murray             BIO_set_retry_write(b);
1405c87c606SMark Murray     }
141e71b7053SJung-uk Kim     return ret;
1425c87c606SMark Murray }
1435c87c606SMark Murray 
fd_ctrl(BIO * b,int cmd,long num,void * ptr)1445c87c606SMark Murray static long fd_ctrl(BIO *b, int cmd, long num, void *ptr)
1455c87c606SMark Murray {
1465c87c606SMark Murray     long ret = 1;
1475c87c606SMark Murray     int *ip;
1485c87c606SMark Murray 
1496f9291ceSJung-uk Kim     switch (cmd) {
1505c87c606SMark Murray     case BIO_CTRL_RESET:
1515c87c606SMark Murray         num = 0;
152e71b7053SJung-uk Kim         /* fall thru */
1535c87c606SMark Murray     case BIO_C_FILE_SEEK:
1543b4e3dcbSSimon L. B. Nielsen         ret = (long)UP_lseek(b->num, num, 0);
1555c87c606SMark Murray         break;
1565c87c606SMark Murray     case BIO_C_FILE_TELL:
1575c87c606SMark Murray     case BIO_CTRL_INFO:
1583b4e3dcbSSimon L. B. Nielsen         ret = (long)UP_lseek(b->num, 0, 1);
1595c87c606SMark Murray         break;
1605c87c606SMark Murray     case BIO_C_SET_FD:
1615c87c606SMark Murray         fd_free(b);
1625c87c606SMark Murray         b->num = *((int *)ptr);
1635c87c606SMark Murray         b->shutdown = (int)num;
1645c87c606SMark Murray         b->init = 1;
1655c87c606SMark Murray         break;
1665c87c606SMark Murray     case BIO_C_GET_FD:
1676f9291ceSJung-uk Kim         if (b->init) {
1685c87c606SMark Murray             ip = (int *)ptr;
1696f9291ceSJung-uk Kim             if (ip != NULL)
1706f9291ceSJung-uk Kim                 *ip = b->num;
1715c87c606SMark Murray             ret = b->num;
1726f9291ceSJung-uk Kim         } else
1735c87c606SMark Murray             ret = -1;
1745c87c606SMark Murray         break;
1755c87c606SMark Murray     case BIO_CTRL_GET_CLOSE:
1765c87c606SMark Murray         ret = b->shutdown;
1775c87c606SMark Murray         break;
1785c87c606SMark Murray     case BIO_CTRL_SET_CLOSE:
1795c87c606SMark Murray         b->shutdown = (int)num;
1805c87c606SMark Murray         break;
1815c87c606SMark Murray     case BIO_CTRL_PENDING:
1825c87c606SMark Murray     case BIO_CTRL_WPENDING:
1835c87c606SMark Murray         ret = 0;
1845c87c606SMark Murray         break;
1855c87c606SMark Murray     case BIO_CTRL_DUP:
1865c87c606SMark Murray     case BIO_CTRL_FLUSH:
1875c87c606SMark Murray         ret = 1;
1885c87c606SMark Murray         break;
18917f01e99SJung-uk Kim     case BIO_CTRL_EOF:
190334d228aSJohn Baldwin         ret = (b->flags & BIO_FLAGS_IN_EOF) != 0;
19117f01e99SJung-uk Kim         break;
1925c87c606SMark Murray     default:
1935c87c606SMark Murray         ret = 0;
1945c87c606SMark Murray         break;
1955c87c606SMark Murray     }
196e71b7053SJung-uk Kim     return ret;
1975c87c606SMark Murray }
1985c87c606SMark Murray 
fd_puts(BIO * bp,const char * str)1995c87c606SMark Murray static int fd_puts(BIO *bp, const char *str)
2005c87c606SMark Murray {
2015c87c606SMark Murray     int n, ret;
2025c87c606SMark Murray 
2035c87c606SMark Murray     n = strlen(str);
2045c87c606SMark Murray     ret = fd_write(bp, str, n);
205e71b7053SJung-uk Kim     return ret;
2065c87c606SMark Murray }
2075c87c606SMark Murray 
fd_gets(BIO * bp,char * buf,int size)2081f13597dSJung-uk Kim static int fd_gets(BIO *bp, char *buf, int size)
2091f13597dSJung-uk Kim {
2101f13597dSJung-uk Kim     int ret = 0;
2111f13597dSJung-uk Kim     char *ptr = buf;
2121f13597dSJung-uk Kim     char *end = buf + size - 1;
2131f13597dSJung-uk Kim 
214e71b7053SJung-uk Kim     while (ptr < end && fd_read(bp, ptr, 1) > 0) {
215e71b7053SJung-uk Kim         if (*ptr++ == '\n')
216e71b7053SJung-uk Kim            break;
217e71b7053SJung-uk Kim     }
2181f13597dSJung-uk Kim 
2191f13597dSJung-uk Kim     ptr[0] = '\0';
2201f13597dSJung-uk Kim 
2211f13597dSJung-uk Kim     if (buf[0] != '\0')
2221f13597dSJung-uk Kim         ret = strlen(buf);
223e71b7053SJung-uk Kim     return ret;
2241f13597dSJung-uk Kim }
2251f13597dSJung-uk Kim 
BIO_fd_should_retry(int i)2265c87c606SMark Murray int BIO_fd_should_retry(int i)
2275c87c606SMark Murray {
2285c87c606SMark Murray     int err;
2295c87c606SMark Murray 
2306f9291ceSJung-uk Kim     if ((i == 0) || (i == -1)) {
2315c87c606SMark Murray         err = get_last_sys_error();
2325c87c606SMark Murray 
233e71b7053SJung-uk Kim         return BIO_fd_non_fatal_error(err);
2345c87c606SMark Murray     }
235e71b7053SJung-uk Kim     return 0;
2365c87c606SMark Murray }
2375c87c606SMark Murray 
BIO_fd_non_fatal_error(int err)2385c87c606SMark Murray int BIO_fd_non_fatal_error(int err)
2395c87c606SMark Murray {
2406f9291ceSJung-uk Kim     switch (err) {
2415c87c606SMark Murray 
2425c87c606SMark Murray # ifdef EWOULDBLOCK
2435c87c606SMark Murray #  ifdef WSAEWOULDBLOCK
2445c87c606SMark Murray #   if WSAEWOULDBLOCK != EWOULDBLOCK
2455c87c606SMark Murray     case EWOULDBLOCK:
2465c87c606SMark Murray #   endif
2475c87c606SMark Murray #  else
2485c87c606SMark Murray     case EWOULDBLOCK:
2495c87c606SMark Murray #  endif
2505c87c606SMark Murray # endif
2515c87c606SMark Murray 
2525c87c606SMark Murray # if defined(ENOTCONN)
2535c87c606SMark Murray     case ENOTCONN:
2545c87c606SMark Murray # endif
2555c87c606SMark Murray 
2565c87c606SMark Murray # ifdef EINTR
2575c87c606SMark Murray     case EINTR:
2585c87c606SMark Murray # endif
2595c87c606SMark Murray 
2605c87c606SMark Murray # ifdef EAGAIN
2615c87c606SMark Murray #  if EWOULDBLOCK != EAGAIN
2625c87c606SMark Murray     case EAGAIN:
2635c87c606SMark Murray #  endif
2645c87c606SMark Murray # endif
2655c87c606SMark Murray 
2665c87c606SMark Murray # ifdef EPROTO
2675c87c606SMark Murray     case EPROTO:
2685c87c606SMark Murray # endif
2695c87c606SMark Murray 
2705c87c606SMark Murray # ifdef EINPROGRESS
2715c87c606SMark Murray     case EINPROGRESS:
2725c87c606SMark Murray # endif
2735c87c606SMark Murray 
2745c87c606SMark Murray # ifdef EALREADY
2755c87c606SMark Murray     case EALREADY:
2765c87c606SMark Murray # endif
277e71b7053SJung-uk Kim         return 1;
2785c87c606SMark Murray     default:
2795c87c606SMark Murray         break;
2805c87c606SMark Murray     }
281e71b7053SJung-uk Kim     return 0;
2825c87c606SMark Murray }
2831f13597dSJung-uk Kim #endif
284