2 * Copyright (c) 1995-2004, Index Data
3 * See the file LICENSE for details.
5 * $Id: tcpip.c,v 1.4 2004-04-29 08:55:17 adam Exp $
20 #if HAVE_OPENSSL_SSL_H
21 #include <openssl/ssl.h>
22 #include <openssl/err.h>
25 #include <yaz/comstack.h>
26 #include <yaz/tcpip.h>
32 #include <netinet/tcp.h>
35 static int tcpip_close(COMSTACK h);
36 static int tcpip_put(COMSTACK h, char *buf, int size);
37 static int tcpip_get(COMSTACK h, char **buf, int *bufsize);
38 static int tcpip_connect(COMSTACK h, void *address);
39 static int tcpip_more(COMSTACK h);
40 static int tcpip_rcvconnect(COMSTACK h);
41 static int tcpip_bind(COMSTACK h, void *address, int mode);
42 static int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
43 int (*check_ip)(void *cd, const char *a, int len, int type),
45 static int tcpip_set_blocking(COMSTACK p, int blocking);
47 #if HAVE_OPENSSL_SSL_H
48 static int ssl_get(COMSTACK h, char **buf, int *bufsize);
49 static int ssl_put(COMSTACK h, char *buf, int size);
52 static COMSTACK tcpip_accept(COMSTACK h);
53 static char *tcpip_addrstr(COMSTACK h);
54 static void *tcpip_straddr(COMSTACK h, const char *str);
63 #define YAZ_SOCKLEN_T int
66 /* this state is used for both SSL and straight TCP/IP */
67 typedef struct tcpip_state
69 char *altbuf; /* alternate buffer for surplus data */
70 int altsize; /* size as xmalloced */
71 int altlen; /* length of data or 0 if none */
73 int written; /* -1 if we aren't writing */
74 int towrite; /* to verify against user input */
75 int (*complete)(const unsigned char *buf, int len); /* length/comple. */
76 struct sockaddr_in addr; /* returned by cs_straddr */
77 char buf[128]; /* returned by cs_addrstr */
78 #if HAVE_OPENSSL_SSL_H
86 static int tcpip_init (void)
88 static int initialized = 0;
94 requested = MAKEWORD(1, 1);
95 if (WSAStartup(requested, &wd))
102 static int tcpip_init (void)
109 * This function is always called through the cs_create() macro.
110 * s >= 0: socket has already been established for us.
112 COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp)
118 unsigned long tru = 1;
125 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
131 if (!(p = (struct comstack *)xmalloc(sizeof(struct comstack))))
133 if (!(state = (struct tcpip_state *)(p->cprivate =
134 xmalloc(sizeof(tcpip_state)))))
137 if (!((p->blocking = blocking)&1))
140 if (ioctlsocket(s, FIONBIO, &tru) < 0)
143 if (fcntl(s, F_SETFL, O_NONBLOCK) < 0)
146 signal (SIGPIPE, SIG_IGN);
153 p->type = tcpip_type;
154 p->protocol = (enum oid_proto) protocol;
156 p->f_connect = tcpip_connect;
157 p->f_rcvconnect = tcpip_rcvconnect;
158 p->f_get = tcpip_get;
159 p->f_put = tcpip_put;
160 p->f_close = tcpip_close;
161 p->f_more = tcpip_more;
162 p->f_bind = tcpip_bind;
163 p->f_listen = tcpip_listen;
164 p->f_accept = tcpip_accept;
165 p->f_addrstr = tcpip_addrstr;
166 p->f_straddr = tcpip_straddr;
167 p->f_set_blocking = tcpip_set_blocking;
169 p->state = new_socket ? CS_ST_UNBND : CS_ST_IDLE; /* state of line */
174 #if HAVE_OPENSSL_SSL_H
175 state->ctx = state->ctx_alloc = 0;
180 state->altsize = state->altlen = 0;
181 state->towrite = state->written = -1;
182 if (protocol == PROTO_WAIS)
183 state->complete = completeWAIS;
185 state->complete = cs_complete_auto;
187 p->timeout = COMSTACK_DEFAULT_TIMEOUT;
188 TRC(fprintf(stderr, "Created new TCPIP comstack\n"));
193 #if HAVE_OPENSSL_SSL_H
195 COMSTACK ssl_type(int s, int blocking, int protocol, void *vp)
200 p = tcpip_type (s, blocking, protocol, 0);
206 state = (tcpip_state *) p->cprivate;
211 SSL_load_error_strings();
212 SSLeay_add_all_algorithms();
214 state->ctx = state->ctx_alloc = SSL_CTX_new (SSLv23_method());
221 /* note: we don't handle already opened socket in SSL mode - yet */
226 int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add,
231 short int port = default_port;
236 TRC(fprintf(stderr, "tcpip_strtoaddress: %s\n", str ? str : "NULL"));
237 add->sin_family = AF_INET;
238 strncpy(buf, str, 511);
240 if ((p = strchr(buf, '/')))
242 if ((p = strchr(buf, ':')))
247 add->sin_port = htons(port);
248 if (!strcmp("@", buf))
249 add->sin_addr.s_addr = INADDR_ANY;
250 else if ((hp = gethostbyname(buf)))
251 memcpy(&add->sin_addr.s_addr, *hp->h_addr_list,
252 sizeof(struct in_addr));
253 else if ((tmpadd = (unsigned) inet_addr(buf)) != 0)
254 memcpy(&add->sin_addr.s_addr, &tmpadd, sizeof(struct in_addr));
260 void *tcpip_straddr(COMSTACK h, const char *str)
262 tcpip_state *sp = (tcpip_state *)h->cprivate;
265 if (h->protocol == PROTO_HTTP)
268 if (!tcpip_strtoaddr_ex (str, &sp->addr, port))
273 struct sockaddr_in *tcpip_strtoaddr(const char *str)
275 static struct sockaddr_in add;
277 if (!tcpip_strtoaddr_ex (str, &add, 210))
282 int tcpip_more(COMSTACK h)
284 tcpip_state *sp = (tcpip_state *)h->cprivate;
286 return sp->altlen && (*sp->complete)((unsigned char *) sp->altbuf,
291 * connect(2) will block (sometimes) - nothing we can do short of doing
292 * weird things like spawning subprocesses or threading or some weird junk
295 int tcpip_connect(COMSTACK h, void *address)
297 struct sockaddr_in *add = (struct sockaddr_in *)address;
298 #if HAVE_OPENSSL_SSL_H
299 tcpip_state *sp = (tcpip_state *)h->cprivate;
304 YAZ_SOCKLEN_T rbufsize = sizeof(recbuflen);
306 TRC(fprintf(stderr, "tcpip_connect\n"));
308 if (h->state != CS_ST_UNBND)
310 h->cerrno = CSOUTSTATE;
314 /* On Suns, you must set a bigger Receive Buffer BEFORE a call to connect
315 * This gives the connect a chance to negotiate with the other side
318 if ( getsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, &rbufsize ) < 0 )
323 TRC(fprintf( stderr, "Current Size of TCP Receive Buffer= %d\n",
325 recbuflen *= 10; /* lets be optimistic */
326 if ( setsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, rbufsize ) < 0 )
331 if ( getsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, &rbufsize ) )
336 TRC(fprintf( stderr, "New Size of TCP Receive Buffer = %d\n",
339 r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add));
343 if (WSAGetLastError() == WSAEWOULDBLOCK)
345 h->event = CS_CONNECT;
346 h->state = CS_ST_CONNECTING;
347 h->io_pending = CS_WANT_WRITE;
351 if (yaz_errno() == EINPROGRESS)
353 h->event = CS_CONNECT;
354 h->state = CS_ST_CONNECTING;
355 h->io_pending = CS_WANT_WRITE|CS_WANT_READ;
362 h->event = CS_CONNECT;
363 h->state = CS_ST_CONNECTING;
365 return tcpip_rcvconnect (h);
371 int tcpip_rcvconnect(COMSTACK h)
373 #if HAVE_OPENSSL_SSL_H
374 tcpip_state *sp = (tcpip_state *)h->cprivate;
376 TRC(fprintf(stderr, "tcpip_rcvconnect\n"));
378 if (h->state == CS_ST_DATAXFER)
380 if (h->state != CS_ST_CONNECTING)
382 h->cerrno = CSOUTSTATE;
385 #if HAVE_OPENSSL_SSL_H
392 sp->ssl = SSL_new (sp->ctx);
393 SSL_set_fd (sp->ssl, h->iofile);
395 res = SSL_connect (sp->ssl);
398 int err = SSL_get_error(sp->ssl, res);
399 if (err == SSL_ERROR_WANT_READ)
401 h->io_pending = CS_WANT_READ;
404 if (err == SSL_ERROR_WANT_WRITE)
406 h->io_pending = CS_WANT_WRITE;
409 h->cerrno = CSERRORSSL;
415 h->state = CS_ST_DATAXFER;
419 #define CERTF "ztest.pem"
420 #define KEYF "ztest.pem"
422 static void tcpip_setsockopt (int fd)
428 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
430 yaz_log(LOG_WARN|LOG_ERRNO, "setsockopt TCP_NODELAY");
432 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
434 yaz_log(LOG_WARN|LOG_ERRNO, "setsockopt SNDBUF");
436 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
438 yaz_log(LOG_WARN|LOG_ERRNO, "setsockopt RCVBUF");
443 static int tcpip_bind(COMSTACK h, void *address, int mode)
445 struct sockaddr *addr = (struct sockaddr *)address;
449 unsigned long one = 1;
452 #if HAVE_OPENSSL_SSL_H
453 tcpip_state *sp = (tcpip_state *)h->cprivate;
459 res = SSL_CTX_use_certificate_file (sp->ctx, CERTF,
463 ERR_print_errors_fp(stderr);
466 res = SSL_CTX_use_PrivateKey_file (sp->ctx, KEYF,
470 ERR_print_errors_fp(stderr);
473 res = SSL_CTX_check_private_key (sp->ctx);
476 ERR_print_errors_fp(stderr);
480 TRC (fprintf (stderr, "ssl_bind\n"));
484 TRC (fprintf (stderr, "tcpip_bind\n"));
487 TRC (fprintf (stderr, "tcpip_bind\n"));
490 if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, (char*)
491 &one, sizeof(one)) < 0)
497 tcpip_setsockopt(h->iofile);
498 if (bind(h->iofile, addr, sizeof(struct sockaddr_in)))
503 if (mode == CS_SERVER && listen(h->iofile, 3) < 0)
508 h->state = CS_ST_IDLE;
509 h->event = CS_LISTEN;
513 int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
514 int (*check_ip)(void *cd, const char *a, int len, int t),
517 struct sockaddr_in addr;
518 YAZ_SOCKLEN_T len = sizeof(addr);
520 TRC(fprintf(stderr, "tcpip_listen pid=%d\n", getpid()));
521 if (h->state != CS_ST_IDLE)
523 h->cerrno = CSOUTSTATE;
526 h->newfd = accept(h->iofile, (struct sockaddr*)&addr, &len);
531 WSAGetLastError() == WSAEWOULDBLOCK
533 yaz_errno() == EWOULDBLOCK
535 #if EAGAIN != EWOULDBLOCK
536 || yaz_errno() == EAGAIN
541 h->cerrno = CSNODATA;
546 if (addrlen && (size_t) (*addrlen) >= sizeof(struct sockaddr_in))
547 memcpy(raddr, &addr, *addrlen = sizeof(struct sockaddr_in));
550 if (check_ip && (*check_ip)(cd, (const char *) &addr,
551 sizeof(addr), AF_INET))
555 closesocket(h->newfd);
562 h->state = CS_ST_INCON;
563 tcpip_setsockopt (h->newfd);
567 COMSTACK tcpip_accept(COMSTACK h)
570 tcpip_state *state, *st = (tcpip_state *)h->cprivate;
572 unsigned long tru = 1;
575 TRC(fprintf(stderr, "tcpip_accept\n"));
576 if (h->state == CS_ST_INCON)
578 if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew))))
582 closesocket(h->newfd);
589 memcpy(cnew, h, sizeof(*h));
590 cnew->iofile = h->newfd;
591 cnew->io_pending = 0;
592 if (!(state = (tcpip_state *)
593 (cnew->cprivate = xmalloc(sizeof(tcpip_state)))))
599 closesocket(h->newfd);
607 if (!(cnew->blocking&1) &&
609 (ioctlsocket(cnew->iofile, FIONBIO, &tru) < 0)
611 (fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0)
619 closesocket(h->newfd);
631 state->altsize = state->altlen = 0;
632 state->towrite = state->written = -1;
633 state->complete = st->complete;
634 cnew->state = CS_ST_ACCEPT;
635 h->state = CS_ST_IDLE;
637 #if HAVE_OPENSSL_SSL_H
638 state->ctx = st->ctx;
639 state->ctx_alloc = 0;
640 state->ssl = st->ssl;
643 state->ssl = SSL_new (state->ctx);
644 SSL_set_fd (state->ssl, cnew->iofile);
649 if (h->state == CS_ST_ACCEPT)
651 #if HAVE_OPENSSL_SSL_H
652 tcpip_state *state = (tcpip_state *)h->cprivate;
655 int res = SSL_accept (state->ssl);
656 TRC(fprintf(stderr, "SSL_accept\n"));
659 int err = SSL_get_error(state->ssl, res);
660 if (err == SSL_ERROR_WANT_READ)
662 h->io_pending = CS_WANT_READ;
665 if (err == SSL_ERROR_WANT_WRITE)
667 h->io_pending = CS_WANT_WRITE;
678 h->cerrno = CSOUTSTATE;
682 h->state = CS_ST_DATAXFER;
687 #define CS_TCPIP_BUFCHUNK 4096
690 * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
691 * 0=connection closed.
693 int tcpip_get(COMSTACK h, char **buf, int *bufsize)
695 tcpip_state *sp = (tcpip_state *)h->cprivate;
697 int tmpi, berlen, rest, req, tomove;
698 int hasread = 0, res;
700 TRC(fprintf(stderr, "tcpip_get: bufsize=%d\n", *bufsize));
701 if (sp->altlen) /* switch buffers */
703 TRC(fprintf(stderr, " %d bytes in altbuf (0x%x)\n", sp->altlen,
704 (unsigned) sp->altbuf));
708 *bufsize = sp->altsize;
709 hasread = sp->altlen;
715 while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
719 if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
722 else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
723 if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
727 /* unfortunatly, sun sometimes forgets to set errno in recv
728 when EWOULDBLOCK etc. would be required (res = -1) */
730 res = recv(h->iofile, *buf + hasread, CS_TCPIP_BUFCHUNK, 0);
731 TRC(fprintf(stderr, " recv res=%d, hasread=%d\n", res, hasread));
734 TRC(fprintf(stderr, " recv errno=%d, (%s)\n", yaz_errno(),
735 strerror(yaz_errno())));
737 if (WSAGetLastError() == WSAEWOULDBLOCK)
739 h->io_pending = CS_WANT_READ;
745 if (yaz_errno() == EWOULDBLOCK
747 #if EAGAIN != EWOULDBLOCK
748 || yaz_errno() == EAGAIN
751 || yaz_errno() == EINPROGRESS
753 || yaz_errno() == ENOENT /* Sun's sometimes set errno to this */
757 h->io_pending = CS_WANT_READ;
760 else if (yaz_errno() == 0)
770 TRC (fprintf (stderr, " Out of read loop with hasread=%d, berlen=%d\n",
772 /* move surplus buffer (or everything if we didn't get a BER rec.) */
773 if (hasread > berlen)
775 tomove = req = hasread - berlen;
776 rest = tomove % CS_TCPIP_BUFCHUNK;
778 req += CS_TCPIP_BUFCHUNK - rest;
781 if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
783 } else if (sp->altsize < req)
784 if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
786 TRC(fprintf(stderr, " Moving %d bytes to altbuf(0x%x)\n", tomove,
787 (unsigned) sp->altbuf));
788 memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
790 if (berlen < CS_TCPIP_BUFCHUNK - 1)
791 *(*buf + berlen) = '\0';
792 return berlen ? berlen : 1;
796 #if HAVE_OPENSSL_SSL_H
798 * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
799 * 0=connection closed.
801 int ssl_get(COMSTACK h, char **buf, int *bufsize)
803 tcpip_state *sp = (tcpip_state *)h->cprivate;
805 int tmpi, berlen, rest, req, tomove;
806 int hasread = 0, res;
808 TRC(fprintf(stderr, "ssl_get: bufsize=%d\n", *bufsize));
809 if (sp->altlen) /* switch buffers */
811 TRC(fprintf(stderr, " %d bytes in altbuf (0x%x)\n", sp->altlen,
812 (unsigned) sp->altbuf));
816 *bufsize = sp->altsize;
817 hasread = sp->altlen;
823 while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
827 if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
830 else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
831 if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
833 res = SSL_read (sp->ssl, *buf + hasread, CS_TCPIP_BUFCHUNK);
834 TRC(fprintf(stderr, " SSL_read res=%d, hasread=%d\n", res, hasread));
837 int ssl_err = SSL_get_error(sp->ssl, res);
838 if (ssl_err == SSL_ERROR_WANT_READ)
840 h->io_pending = CS_WANT_READ;
843 if (ssl_err == SSL_ERROR_WANT_WRITE)
845 h->io_pending = CS_WANT_WRITE;
850 h->cerrno = CSERRORSSL;
855 TRC (fprintf (stderr, " Out of read loop with hasread=%d, berlen=%d\n",
857 /* move surplus buffer (or everything if we didn't get a BER rec.) */
858 if (hasread > berlen)
860 tomove = req = hasread - berlen;
861 rest = tomove % CS_TCPIP_BUFCHUNK;
863 req += CS_TCPIP_BUFCHUNK - rest;
866 if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
868 } else if (sp->altsize < req)
869 if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
871 TRC(fprintf(stderr, " Moving %d bytes to altbuf(0x%x)\n", tomove,
872 (unsigned) sp->altbuf));
873 memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
875 if (berlen < CS_TCPIP_BUFCHUNK - 1)
876 *(*buf + berlen) = '\0';
877 return berlen ? berlen : 1;
883 * In nonblocking mode, you must call again with same buffer while
886 int tcpip_put(COMSTACK h, char *buf, int size)
889 struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
891 TRC(fprintf(stderr, "tcpip_put: size=%d\n", size));
894 if (state->towrite < 0)
896 state->towrite = size;
899 else if (state->towrite != size)
901 h->cerrno = CSWRONGBUF;
904 while (state->towrite > state->written)
907 send(h->iofile, buf + state->written, size -
918 WSAGetLastError() == WSAEWOULDBLOCK
920 yaz_errno() == EWOULDBLOCK
922 #if EAGAIN != EWOULDBLOCK
923 || yaz_errno() == EAGAIN
927 || yaz_errno() == ENOENT /* Sun's sometimes set errno to this value! */
929 || yaz_errno() == EINPROGRESS
933 TRC(fprintf(stderr, " Flow control stop\n"));
934 h->io_pending = CS_WANT_WRITE;
940 state->written += res;
941 TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n",
942 res, state->written, size));
944 state->towrite = state->written = -1;
945 TRC(fprintf(stderr, " Ok\n"));
950 #if HAVE_OPENSSL_SSL_H
953 * In nonblocking mode, you must call again with same buffer while
956 int ssl_put(COMSTACK h, char *buf, int size)
959 struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
961 TRC(fprintf(stderr, "ssl_put: size=%d\n", size));
964 if (state->towrite < 0)
966 state->towrite = size;
969 else if (state->towrite != size)
971 h->cerrno = CSWRONGBUF;
974 while (state->towrite > state->written)
976 res = SSL_write (state->ssl, buf + state->written,
977 size - state->written);
980 int ssl_err = SSL_get_error(state->ssl, res);
981 if (ssl_err == SSL_ERROR_WANT_READ)
983 h->io_pending = CS_WANT_READ;
986 if (ssl_err == SSL_ERROR_WANT_WRITE)
988 h->io_pending = CS_WANT_WRITE;
991 h->cerrno = CSERRORSSL;
994 state->written += res;
995 TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n",
996 res, state->written, size));
998 state->towrite = state->written = -1;
999 TRC(fprintf(stderr, " Ok\n"));
1004 int tcpip_close(COMSTACK h)
1006 tcpip_state *sp = (struct tcpip_state *)h->cprivate;
1008 TRC(fprintf(stderr, "tcpip_close\n"));
1009 if (h->iofile != -1)
1011 #if HAVE_OPENSSL_SSL_H
1014 SSL_shutdown (sp->ssl);
1018 closesocket(h->iofile);
1025 #if HAVE_OPENSSL_SSL_H
1028 TRC (fprintf(stderr, "SSL_free\n"));
1033 SSL_CTX_free (sp->ctx_alloc);
1040 char *tcpip_addrstr(COMSTACK h)
1042 struct sockaddr_in addr;
1043 tcpip_state *sp = (struct tcpip_state *)h->cprivate;
1044 char *r = 0, *buf = sp->buf;
1046 struct hostent *host;
1049 if (getpeername(h->iofile, (struct sockaddr*) &addr, &len) < 0)
1051 h->cerrno = CSYSERR;
1054 if (!(h->blocking&2)) {
1055 if ((host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr),
1057 r = (char*) host->h_name;
1060 r = inet_ntoa(addr.sin_addr);
1061 if (h->protocol == PROTO_HTTP)
1062 sprintf(buf, "http:%s", r);
1064 sprintf(buf, "tcp:%s", r);
1065 #if HAVE_OPENSSL_SSL_H
1068 if (h->protocol == PROTO_HTTP)
1069 sprintf(buf, "https:%s", r);
1071 sprintf(buf, "ssl:%s", r);
1077 int static tcpip_set_blocking(COMSTACK p, int blocking)
1081 if (p->blocking == blocking)
1085 if (ioctlsocket(p->iofile, FIONBIO, &flag) < 0)
1088 flag = fcntl(p->iofile, F_GETFL, 0);
1090 flag = flag & ~O_NONBLOCK;
1092 flag = flag | O_NONBLOCK;
1093 if (fcntl(p->iofile, F_SETFL, flag) < 0)
1096 p->blocking = blocking;
1100 #if HAVE_OPENSSL_SSL_H
1101 void *cs_get_ssl(COMSTACK cs)
1103 struct tcpip_state *state;
1104 if (!cs || cs->type != ssl_type)
1106 state = (struct tcpip_state *) cs->cprivate;
1110 int cs_get_peer_certificate_x509(COMSTACK cs, char **buf, int *len)
1112 SSL *ssl = cs_get_ssl(cs);
1115 X509 *server_cert = SSL_get_peer_certificate (ssl);
1118 BIO *bio = BIO_new(BIO_s_mem());
1120 /* get PEM buffer in memory */
1121 PEM_write_bio_X509(bio, server_cert);
1122 *len = BIO_get_mem_data(bio, &pem_buf);
1123 *buf = xmalloc(*len);
1124 memcpy(*buf, pem_buf, *len);
1132 void *cs_get_ssl(COMSTACK cs)
1137 int cs_get_peer_certificate_x509(COMSTACK cs, char **buf, int *len)